<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 6.3.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"chuangges.gitee.io","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"right","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":"mac"},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="vue 预览上传、uniapp 预览上传、minio 文件管理、补丁版本管理">
<meta property="og:type" content="article">
<meta property="og:title" content="文档的在线预览和上传下载">
<meta property="og:url" content="https://chuangges.gitee.io/2023/01/17/20-%E8%B7%A8%E5%B9%B3%E5%8F%B0%E6%96%87%E6%A1%A3/index.html">
<meta property="og:site_name" content="闯哥要去流浪了">
<meta property="og:description" content="vue 预览上传、uniapp 预览上传、minio 文件管理、补丁版本管理">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://chuangges.gitee.io/images/web/fileobj.png">
<meta property="article:published_time" content="2023-01-17T08:11:06.000Z">
<meta property="article:modified_time" content="2023-10-11T10:40:48.809Z">
<meta property="article:author" content="chuangges">
<meta property="article:tag" content="前端技术栈">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://chuangges.gitee.io/images/web/fileobj.png">

<link rel="canonical" href="https://chuangges.gitee.io/2023/01/17/20-%E8%B7%A8%E5%B9%B3%E5%8F%B0%E6%96%87%E6%A1%A3/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>文档的在线预览和上传下载 | 闯哥要去流浪了</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/atom.xml" title="闯哥要去流浪了" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">闯哥要去流浪了</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">愿你岁月可回首，且以深情共白头</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://chuangges.gitee.io/2023/01/17/20-%E8%B7%A8%E5%B9%B3%E5%8F%B0%E6%96%87%E6%A1%A3/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/chuang.png">
      <meta itemprop="name" content="chuangges">
      <meta itemprop="description" content="chuangge's blog.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="闯哥要去流浪了">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          文档的在线预览和上传下载
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2023-01-17 16:11:06" itemprop="dateCreated datePublished" datetime="2023-01-17T16:11:06+08:00">2023-01-17</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2023-10-11 18:40:48" itemprop="dateModified" datetime="2023-10-11T18:40:48+08:00">2023-10-11</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E5%89%8D%E7%AB%AF%E6%8A%80%E6%9C%AF%E6%A0%88/" itemprop="url" rel="index"><span itemprop="name">前端技术栈</span></a>
                </span>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="far fa-file-word"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>53k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="far fa-clock"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>48 分钟</span>
            </span>
            <div class="post-description">vue 预览上传、uniapp 预览上传、minio 文件管理、补丁版本管理</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h1 id="一、vue-在线预览"><a href="#一、vue-在线预览" class="headerlink" title="一、vue 在线预览"></a>一、vue 在线预览</h1><table>
<thead>
<tr>
<th>文档格式</th>
<th>老的开源组件</th>
<th>替代开源组件</th>
</tr>
</thead>
<tbody><tr>
<td>docx</td>
<td>mammoth</td>
<td>docx-preview</td>
</tr>
<tr>
<td>pptx</td>
<td>pptxjs</td>
<td>pptxjs 改造</td>
</tr>
<tr>
<td>pdf</td>
<td>pdfjs</td>
<td>pdfjs</td>
</tr>
<tr>
<td>xlsx</td>
<td>sheetjs、handsontable</td>
<td>exceljs、handsontable</td>
</tr>
<tr>
<td>image</td>
<td>jquery.verySimpleImageViewer</td>
<td>v-viewer</td>
</tr>
</tbody></table>
<h2 id="Docx"><a href="#Docx" class="headerlink" title="Docx"></a>Docx</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 1、安装插件：npm i docx-preview</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 2、引入方法：renderAsync</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 3、渲染文档：传入数据 blob</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">import</span> &#123; defaultOptions, renderAsync &#125; <span class="keyword">from</span> <span class="string">&quot;docx-preview&quot;</span>;</span><br><span class="line"><span class="title function_">renderAsync</span>(buffer, <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;container&quot;</span>), <span class="literal">null</span>,</span><br><span class="line">  <span class="attr">options</span>: &#123;</span><br><span class="line">      <span class="attr">className</span>: string = <span class="string">&quot;docx&quot;</span>,     <span class="comment">// 默认文档的类名/前缀</span></span><br><span class="line">      <span class="attr">inWrapper</span>: boolean = <span class="literal">true</span>,      <span class="comment">// 围绕内容渲染包装器</span></span><br><span class="line">      <span class="attr">ignoreWidth</span>: boolean = <span class="literal">false</span>,   <span class="comment">// 禁止页面渲染宽度</span></span><br><span class="line">      <span class="attr">ignoreHeight</span>: boolean = <span class="literal">false</span>,  <span class="comment">// 禁止页面渲染高度</span></span><br><span class="line">      <span class="attr">ignoreFonts</span>: boolean = <span class="literal">false</span>,   <span class="comment">// 禁止字体渲染</span></span><br><span class="line">      <span class="attr">breakPages</span>: boolean = <span class="literal">true</span>,     <span class="comment">// 分页符上启用分页</span></span><br><span class="line">      <span class="attr">ignoreLastRenderedPageBreak</span>: boolean = <span class="literal">true</span>, <span class="comment">// 忽略分页 last</span></span><br><span class="line">      <span class="attr">experimental</span>: boolean = <span class="literal">false</span>,  <span class="comment">// 启用实验性功能（制表符停止计算）</span></span><br><span class="line">      <span class="attr">trimXmlDeclaration</span>: boolean = <span class="literal">true</span>,  <span class="comment">// 文档解析前删除 xml 声明</span></span><br><span class="line">      <span class="attr">debug</span>: boolean = <span class="literal">false</span>,         <span class="comment">// 启用额外的日志记录</span></span><br><span class="line">  &#125;</span><br><span class="line">);</span><br></pre></td></tr></table></figure>

<h2 id="Pdf"><a href="#Pdf" class="headerlink" title="Pdf"></a>Pdf</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 1、安装插件：npm i pdfjs-dist</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 2、处理数据：PDFJS.getDocument</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 3、创建画布并渲染：page.render</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> <span class="variable constant_">PDFJS</span> <span class="keyword">from</span> <span class="string">&quot;pdfjs-dist/legacy/build/pdf&quot;</span>;</span><br><span class="line"><span class="keyword">let</span> src = <span class="built_in">require</span>(<span class="string">&quot;pdfjs-dist/legacy/build/pdf.worker.entry.js&quot;</span>);</span><br><span class="line"><span class="variable constant_">PDFJS</span>.<span class="property">GlobalWorkerOptions</span>.<span class="property">workerSrc</span> = src   <span class="comment">// 设置引入地址</span></span><br><span class="line"><span class="variable constant_">PDFJS</span>.<span class="title function_">getDocument</span>(data).<span class="property">promise</span>.<span class="title function_">then</span>(<span class="function"><span class="params">pdfDoc</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> numPages = pdfDoc.<span class="property">numPages</span>;</span><br><span class="line">    pdfDoc.<span class="title function_">getPage</span>(<span class="number">1</span>).<span class="title function_">then</span>(<span class="function"><span class="params">page</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> canvas = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;the_canvas&quot;</span>);</span><br><span class="line">        <span class="keyword">const</span> ctx = canvas.<span class="title function_">getContext</span>(<span class="string">&quot;2d&quot;</span>);</span><br><span class="line">        <span class="keyword">const</span> dpr = <span class="variable language_">window</span>.<span class="property">devicePixelRatio</span> || <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">const</span> bsr =</span><br><span class="line">            ctx.<span class="property">webkitBackingStorePixelRatio</span> ||</span><br><span class="line">            ctx.<span class="property">mozBackingStorePixelRatio</span> ||</span><br><span class="line">            ctx.<span class="property">msBackingStorePixelRatio</span> ||</span><br><span class="line">            ctx.<span class="property">oBackingStorePixelRatio</span> ||</span><br><span class="line">            ctx.<span class="property">backingStorePixelRatio</span> ||</span><br><span class="line">            <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">const</span> ratio = dpr / bsr;</span><br><span class="line">        <span class="keyword">const</span> viewport = page.<span class="title function_">getViewport</span>(&#123; <span class="attr">scale</span>: <span class="number">1</span> &#125;);</span><br><span class="line">        canvas.<span class="property">width</span> = viewport.<span class="property">width</span> * ratio;</span><br><span class="line">        canvas.<span class="property">height</span> = viewport.<span class="property">height</span> * ratio;</span><br><span class="line">        canvas.<span class="property">style</span>.<span class="property">width</span> = viewport.<span class="property">width</span> + <span class="string">&quot;px&quot;</span>;</span><br><span class="line">        canvas.<span class="property">style</span>.<span class="property">height</span> = viewport.<span class="property">height</span> + <span class="string">&quot;px&quot;</span>;</span><br><span class="line">        ctx.<span class="title function_">setTransform</span>(ratio, <span class="number">0</span>, <span class="number">0</span>, ratio, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">        <span class="keyword">const</span> renderContext = &#123;</span><br><span class="line">            <span class="attr">canvasContext</span>: ctx,</span><br><span class="line">            <span class="attr">viewport</span>: viewport,</span><br><span class="line">        &#125;;</span><br><span class="line">        page.<span class="title function_">render</span>(renderContext);</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<h2 id="Excel"><a href="#Excel" class="headerlink" title="Excel"></a>Excel</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 1、下载库 exceljs、handsontable</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 2、通过 exceljs 读取文件的数据</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 3、通过 workbook.getWorksheet 获取工作表数据并处理为二维数组</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 4、引入 <span class="doctag">@handsontable</span>/vue 的组件 HotTable</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 5、通过 settings 属性将配置参数和二维数组传入组件渲染为 excel</span></span><br><span class="line"><span class="comment">**/</span> </span><br><span class="line"><span class="comment">// 加载 excel 数据：第一页数据、每一行数据</span></span><br><span class="line"><span class="keyword">new</span> <span class="title class_">ExcelJS</span>.<span class="title class_">Workbook</span>().<span class="property">xlsx</span>.<span class="title function_">load</span>(buffer)).<span class="title function_">then</span>(<span class="function"><span class="params">workbook</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> ws = workbook.<span class="title function_">getWorksheet</span>(<span class="number">1</span>);</span><br><span class="line">    <span class="keyword">const</span> data = ws.<span class="title function_">getRows</span>(<span class="number">1</span>, ws.<span class="property">actualRowCount</span>);</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 渲染页面</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">HotTable</span> &#125; <span class="keyword">from</span> <span class="string">&quot;@handsontable/vue&quot;</span>;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">hot-table</span> <span class="attr">:settings</span>=<span class="string">&quot;hotSettings&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">hot-table</span>&gt;</span></span></span><br><span class="line">hotSettings = &#123;</span><br><span class="line">    <span class="attr">language</span>: <span class="string">&quot;zh-CN&quot;</span>,</span><br><span class="line">    <span class="attr">readOnly</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="attr">data</span>: <span class="variable language_">this</span>.<span class="property">data</span>,</span><br><span class="line">    <span class="attr">cell</span>: <span class="variable language_">this</span>.<span class="property">cell</span>,</span><br><span class="line">    <span class="attr">mergeCells</span>: <span class="variable language_">this</span>.<span class="property">merge</span>,</span><br><span class="line">    <span class="attr">colHeaders</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="attr">rowHeaders</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="attr">height</span>: <span class="string">&quot;calc(100vh - 107px)&quot;</span>,</span><br><span class="line">    <span class="comment">// contextMenu: true,</span></span><br><span class="line">    <span class="comment">// manualRowMove: true,</span></span><br><span class="line">    <span class="comment">// 关闭外部点击取消选中时间的行为</span></span><br><span class="line">    <span class="attr">outsideClickDeselects</span>: <span class="literal">false</span>,</span><br><span class="line">    <span class="comment">// fillHandle: &#123;</span></span><br><span class="line">    <span class="comment">//   direction: &#x27;vertical&#x27;,</span></span><br><span class="line">    <span class="comment">//   autoInsertRow: true</span></span><br><span class="line">    <span class="comment">// &#125;,</span></span><br><span class="line">    <span class="comment">// afterSelectionEnd: this.afterSelectionEnd,</span></span><br><span class="line">    <span class="comment">// bindRowsWithHeaders: &#x27;strict&#x27;,</span></span><br><span class="line">    <span class="attr">licenseKey</span>: <span class="string">&quot;non-commercial-and-evaluation&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="pptx"><a href="#pptx" class="headerlink" title="pptx"></a>pptx</h2><blockquote>
<p>通过 jszip 库加载二进制文件，然后经过一些列处理和转换，具体实现可查看 <a target="_blank" rel="external nofollow noopener noreferrer" href="https://gitee.com/chuangges/file-preview">file-view</a>。</p>
</blockquote>
<h1 id="二、vue-文件分块上传"><a href="#二、vue-文件分块上传" class="headerlink" title="二、vue 文件分块上传"></a>二、vue 文件分块上传</h1><blockquote>
<p>前端通过选择文件获取对象 <code>File</code>，然后通过 <code>File.prototype.slice</code> 实现资源分块并基于 <code>Promise.all/allSettled</code> 整合包含序号和当前分块等信息的多个请求，某个请求失败则可重传。服务端获取合并信息后可通过 <code>NodeJS 读写流</code>将切片数据通过管道输入文件。</p>
</blockquote>
<h2 id="文件流操作"><a href="#文件流操作" class="headerlink" title="文件流操作"></a>文件流操作</h2><blockquote>
<p>数据流指连续的数据序列，可以从一个源传输到另一个目的地。前端开发中的文件可以被看作数据流的一种形式，文件操作包括读取文件内容、写入数据到文件，对文件进行删除或重命名等，相关对象主要如下：</p>
</blockquote>
  <div align="center">
      <img src="" data-original="/images/web/fileobj.png" alt="相关配置" width="90%">
  </div>

  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> 二进制存储对象：本质是一串无格式的乱码数字。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> Blob：将一段内存数据封装为一个整体的只读对象，适用于预览上传和下载。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> ArrayBuffer：模拟堆内存缓存区的底层原始对象，适用于操作二进制数据。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> Buffer：V8 堆内存之外的一块原始内存，用于 NodeJS 环境的 I/O 操作。</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> Blob 派生对象。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> File：包括 input 文件选择的 FileList、元素拖拽的 DataTransfer。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> FileReader：提供了将 Blob 数据读取为文本和字符串等指定格式的方法。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> URL：临时指向 Blob 内容的地址对象，常用于浏览器端的文件预览和下载。</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> ArrayBuffer 操作对象：本质是一个二进制数据的抽象化数组结构。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> TypedArray：成员类型相同而且没有空位，可读取但本身并不存储。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> DataView：成员可以是不同类型，读写时可自行设定大小端字节序。</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>, &#123; useState &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">FileInput</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> [fileContent, setFileContent] = <span class="title function_">useState</span>(<span class="string">&#x27;&#x27;</span>);</span><br><span class="line">    <span class="comment">// 读取文件内容到 ArrayBuffer</span></span><br><span class="line">    <span class="keyword">function</span> <span class="title function_">readFileToArrayBuffer</span>(<span class="params">file</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">            <span class="keyword">const</span> reader = <span class="keyword">new</span> <span class="title class_">FileReader</span>();</span><br><span class="line">            reader.<span class="property">onload</span> = <span class="keyword">function</span>(<span class="params">event</span>) &#123;</span><br><span class="line">                <span class="keyword">const</span> arrayBuffer = event.<span class="property">target</span>.<span class="property">result</span>;</span><br><span class="line">                <span class="title function_">resolve</span>(arrayBuffer);</span><br><span class="line">            &#125;;</span><br><span class="line">            reader.<span class="title function_">readAsArrayBuffer</span>(file);</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// ArrayBuffer 转为十六进制字符串</span></span><br><span class="line">    <span class="keyword">function</span> <span class="title function_">arrayBufferToHexString</span>(<span class="params">arrayBuffer</span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> uint8Array = <span class="keyword">new</span> <span class="title class_">Uint8Array</span>(arrayBuffer);</span><br><span class="line">        <span class="keyword">let</span> hexString = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; uint8Array.<span class="property">length</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">const</span> hex = uint8Array[i].<span class="title function_">toString</span>(<span class="number">16</span>).<span class="title function_">padStart</span>(<span class="number">2</span>, <span class="string">&#x27;0&#x27;</span>);</span><br><span class="line">            hexString += hex;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> hexString;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 处理文件选择事件</span></span><br><span class="line">    <span class="keyword">function</span> <span class="title function_">handleFileChange</span>(<span class="params">event</span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> file = event.<span class="property">target</span>.<span class="property">files</span>[<span class="number">0</span>];</span><br><span class="line">        <span class="keyword">if</span> (!file) &#123;</span><br><span class="line">            <span class="title function_">setFileContent</span>(<span class="string">&#x27;请选择一个文件&#x27;</span>);</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="title function_">readFileToArrayBuffer</span>(file)</span><br><span class="line">        .<span class="title function_">then</span>(<span class="function"><span class="params">arrayBuffer</span> =&gt;</span> &#123;</span><br><span class="line">            <span class="keyword">const</span> hexString = <span class="title function_">arrayBufferToHexString</span>(arrayBuffer);</span><br><span class="line">            <span class="title function_">setFileContent</span>(hexString);</span><br><span class="line">        &#125;)</span><br><span class="line">        .<span class="title function_">catch</span>(<span class="function"><span class="params">error</span> =&gt;</span> &#123;</span><br><span class="line">            <span class="title function_">setFileContent</span>(<span class="string">&#x27;文件读取失败：&#x27;</span> + error)</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;file&quot;</span> <span class="attr">onChange</span>=<span class="string">&#123;handleFileChange&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;<span class="name">span</span>&gt;</span>&#123;fileContent&#125;<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    );</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">FileInput</span>;</span><br></pre></td></tr></table></figure>


<h2 id="切片上传"><a href="#切片上传" class="headerlink" title="切片上传"></a>切片上传</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 搭建项目</span></span><br><span class="line">pnpm create vite</span><br><span class="line"></span><br><span class="line"><span class="comment">// src/request.js：封装请求</span></span><br><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">&quot;axios&quot;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">getFileChunk</span> = (<span class="params">file: File, chunkSize: number</span>) =&gt; &#123; </span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resovle, reject</span>) =&gt;</span> &#123; </span><br><span class="line">        <span class="keyword">let</span> blobSlice = <span class="title class_">File</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">slice</span> || </span><br><span class="line">        <span class="title class_">File</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">mozSlice</span> || <span class="title class_">File</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">webkitSlice</span>; </span><br><span class="line">        <span class="keyword">let</span> spark = <span class="keyword">new</span> <span class="title class_">SparkMD5</span>.<span class="title class_">ArrayBuffer</span>();</span><br><span class="line">        <span class="keyword">let</span> fileReader = <span class="keyword">new</span> <span class="title class_">FileReader</span>(); </span><br><span class="line">        <span class="keyword">let</span> chunkCur = <span class="number">0</span>;    <span class="comment">// 当前分块</span></span><br><span class="line">        <span class="keyword">let</span> chunkList = []   <span class="comment">// 分块列表</span></span><br><span class="line">        <span class="keyword">let</span> chunkLen = <span class="title class_">Math</span>.<span class="title function_">ceil</span>(file.<span class="property">size</span> / chunkSize);</span><br><span class="line">        fileReader.<span class="property">onload</span> = <span class="keyword">function</span> (<span class="params">e</span>) &#123;   </span><br><span class="line">            <span class="keyword">const</span> chunk = e.<span class="property">target</span>.<span class="property">result</span>;  </span><br><span class="line">            spark.<span class="title function_">append</span>(chunk);    </span><br><span class="line">            chunkCur++;</span><br><span class="line">            <span class="keyword">if</span> (chunkLen &gt; chunkCur) &#123;     </span><br><span class="line">                <span class="title function_">loadNext</span>();   </span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;    </span><br><span class="line">                <span class="keyword">let</span> hash = spark.<span class="title function_">end</span>();   </span><br><span class="line">                <span class="title function_">resovle</span>(&#123;hash, chunkList&#125;);   </span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;   </span><br><span class="line">  </span><br><span class="line">        fileReader.<span class="property">onerror</span> = <span class="function"><span class="params">err</span> =&gt;</span> &#123;    </span><br><span class="line">            <span class="title function_">reject</span>(err);</span><br><span class="line">        &#125;;  </span><br><span class="line">        <span class="title function_">loadNext</span>();</span><br><span class="line">        <span class="keyword">function</span> <span class="title function_">loadNext</span>(<span class="params"></span>) &#123;    </span><br><span class="line">            <span class="keyword">const</span> start = chunkCur * chunkSize;</span><br><span class="line">            <span class="keyword">const</span> end = <span class="title class_">Math</span>.<span class="title function_">min</span>(start + chunkSize, file.<span class="property">size</span>);</span><br><span class="line">            <span class="keyword">const</span> chunk = blobSlice.<span class="title function_">call</span>(file, start, end); </span><br><span class="line">            chunkList.<span class="title function_">push</span>(chunk);    </span><br><span class="line">            fileReader.<span class="title function_">readAsArrayBuffer</span>(chunk);  </span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">onUpload</span> = (<span class="params">file: any</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">const</span> chunkSize = <span class="number">5</span> * <span class="number">1024</span> * <span class="number">1024</span>;</span><br><span class="line">    <span class="keyword">const</span> &#123;fileHash, chunkList&#125; = <span class="keyword">await</span> <span class="title function_">getFileChunk</span>(file, chunkSize); </span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">onProgress</span> = item =&gt; <span class="function"><span class="params">e</span> =&gt;</span> &#123; </span><br><span class="line">        item.<span class="property">percent</span> = <span class="title class_">Math</span>.<span class="title function_">round</span>((e.<span class="property">loaded</span> / e.<span class="property">total</span>) * <span class="number">100</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">const</span> requests = chunkList.<span class="title function_">map</span>(<span class="function">(<span class="params">item, i</span>) =&gt;</span> &#123;  </span><br><span class="line">        <span class="keyword">const</span> formData = <span class="keyword">new</span> <span class="title class_">FormData</span>();  </span><br><span class="line">        formdata.<span class="title function_">append</span>(<span class="string">&#x27;chunkIndex&#x27;</span>, i.<span class="title function_">toString</span>())</span><br><span class="line">        formdata.<span class="title function_">append</span>(<span class="string">&#x27;chunkSize&#x27;</span>, item.<span class="property">size</span>)</span><br><span class="line">        formData.<span class="title function_">append</span>(<span class="string">&#x27;file&#x27;</span>, item);</span><br><span class="line">        formdata.<span class="title function_">append</span>(<span class="string">&#x27;fileSize&#x27;</span>, file.<span class="property">size</span>)</span><br><span class="line">        formData.<span class="title function_">append</span>(<span class="string">&#x27;fileName&#x27;</span>, file.<span class="property">name</span>);   </span><br><span class="line">        formData.<span class="title function_">append</span>(<span class="string">&#x27;fileHash&#x27;</span>, fileHash);  </span><br><span class="line">        <span class="keyword">return</span> axios.<span class="title function_">post</span>(<span class="string">&#x27;/upload&#x27;</span>, formData, <span class="title function_">onProgress</span>(item)); </span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="title class_">Promise</span>.<span class="title function_">all</span>(requests).<span class="title function_">then</span>(<span class="function">() =&gt;</span> &#123; </span><br><span class="line">        axios.<span class="title function_">post</span>(<span class="string">&#x27;/mergeChunks&#x27;</span>, &#123; <span class="attr">size</span>: chunkSize, filename &#125;)</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="切片下载"><a href="#切片下载" class="headerlink" title="切片下载"></a>切片下载</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 服务器端将大文件切割成包含唯一标识的多个切片，客户端下载完成后拼接。</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">downloadFile</span>(<span class="params"></span>) &#123;</span><br><span class="line">    axios.<span class="title function_">get</span>(<span class="string">&#x27;/download&#x27;</span>, &#123;</span><br><span class="line">        <span class="attr">headers</span>: &#123; <span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&#x27;application/json&#x27;</span> &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">    .<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> res.<span class="title function_">json</span>())</span><br><span class="line">    .<span class="title function_">then</span>(<span class="function"><span class="params">data</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> chunkSize = data.<span class="property">chunkSize</span>;</span><br><span class="line">        <span class="keyword">const</span> fileSize = data.<span class="property">fileSize</span>;</span><br><span class="line">        <span class="keyword">const</span> chunkLen = <span class="title class_">Math</span>.<span class="title function_">ceil</span>(file.<span class="property">size</span> / chunkSize);</span><br><span class="line">        <span class="keyword">let</span> downloadedChunks = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">let</span> chunkList = [];</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">let</span> chunkIndex = <span class="number">0</span>; chunkIndex &lt; chunkLen; chunkIndex++) &#123;</span><br><span class="line">            <span class="title function_">fetch</span>(<span class="string">`/download/<span class="subst">$&#123;chunkIndex&#125;</span>`</span>, &#123; <span class="attr">method</span>: <span class="string">&#x27;GET&#x27;</span> &#125;)</span><br><span class="line">            .<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> res.<span class="title function_">blob</span>())</span><br><span class="line">            .<span class="title function_">then</span>(<span class="function"><span class="params">chunk</span> =&gt;</span> &#123;</span><br><span class="line">                downloadedChunks++;</span><br><span class="line">                chunkList.<span class="title function_">push</span>(chunk);</span><br><span class="line">                <span class="keyword">if</span> (downloadedChunks == chunkLen) &#123;</span><br><span class="line">                    <span class="keyword">const</span> mBlob = <span class="keyword">new</span> <span class="title class_">Blob</span>(chunkList);</span><br><span class="line">                    <span class="keyword">const</span> blobUrl = <span class="variable language_">window</span>.<span class="property">URL</span>.<span class="title function_">createObjectURL</span>(mBlob);</span><br><span class="line">                    <span class="keyword">const</span> link = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;a&#x27;</span>);</span><br><span class="line">                    link.<span class="property">href</span> = blobUrl;</span><br><span class="line">                    link.<span class="title function_">setAttribute</span>(<span class="string">&#x27;download&#x27;</span>, <span class="string">&#x27;file.txt&#x27;</span>);</span><br><span class="line">                    link.<span class="title function_">click</span>();</span><br><span class="line">                    <span class="variable language_">window</span>.<span class="property">URL</span>.<span class="title function_">revokeObjectURL</span>(blobUrl);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">    .<span class="title function_">catch</span>(<span class="function"><span class="params">error</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&#x27;文件下载失败:&#x27;</span>, error);</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="服务端处理"><a href="#服务端处理" class="headerlink" title="服务端处理"></a>服务端处理</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 1、搭建服务</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> koa2 搭建简单服务，端口为 3001</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> <span class="variable">koa</span>-body 接收数据 &#x27;Content-Type&#x27;: &#x27;multipart/form-data&#x27;</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> <span class="variable">koa</span>-router 注册服务端路由</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> <span class="variable">koa2</span>-cors 处理跨域问题</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 2、server/server.js：处理接收和整合分块资源</span></span><br><span class="line"><span class="keyword">let</span> chunk;</span><br><span class="line">router.<span class="title function_">post</span>(<span class="string">&#x27;/upload&#x27;</span>, </span><br><span class="line"><span class="title function_">koaBody</span>(&#123;   <span class="comment">// 处理文件数据  </span></span><br><span class="line">    <span class="attr">multipart</span>: <span class="literal">true</span>,  </span><br><span class="line">    <span class="attr">formidable</span>: &#123;  </span><br><span class="line">        <span class="attr">uploadDir</span>: outputPath,    </span><br><span class="line">        <span class="attr">onFileBegin</span>: <span class="function">(<span class="params">name, file</span>) =&gt;</span> &#123;      </span><br><span class="line">            <span class="keyword">const</span> [fileName, fileHash, index] = name.<span class="title function_">split</span>(<span class="string">&#x27;-&#x27;</span>);      </span><br><span class="line">            <span class="keyword">const</span> dir = path.<span class="title function_">join</span>(outputPath, filename);         </span><br><span class="line">            chunk = &#123; filename, fileHash, index &#125;;      </span><br><span class="line">            <span class="keyword">if</span> (!fs.<span class="title function_">existsSync</span>(dir)) &#123; fs.<span class="title function_">mkdirSync</span>(dir); &#125; </span><br><span class="line">            file.<span class="property">path</span> = <span class="string">`<span class="subst">$&#123;dir&#125;</span>/<span class="subst">$&#123;fileHash&#125;</span>-<span class="subst">$&#123;index&#125;</span>`</span>; <span class="comment">// 完整路径</span></span><br><span class="line">        &#125;,   </span><br><span class="line">        <span class="attr">onError</span>: <span class="function">(<span class="params">error</span>) =&gt;</span> &#123;     </span><br><span class="line">            app.<span class="property">status</span> = <span class="number">400</span>;  </span><br><span class="line">            app.<span class="property">body</span> = &#123;<span class="attr">code</span>: <span class="number">400</span>, <span class="attr">msg</span>: <span class="string">&quot;上传失败&quot;</span>, <span class="attr">data</span>: chunk&#125;;      </span><br><span class="line">            <span class="keyword">return</span>;    </span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;),</span><br><span class="line"><span class="keyword">async</span> (ctx) =&gt; &#123;    <span class="comment">// 处理响应 </span></span><br><span class="line">    ctx.<span class="title function_">set</span>(<span class="string">&quot;Content-Type&quot;</span>, <span class="string">&quot;application/json&quot;</span>); </span><br><span class="line">    ctx.<span class="property">body</span> = <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123;   </span><br><span class="line">        <span class="attr">code</span>: <span class="number">2000</span>,   </span><br><span class="line">        <span class="attr">message</span>: <span class="string">&#x27;upload successfully！&#x27;</span> </span><br><span class="line">    &#125;); </span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 3、整合分块：合并请求、管道处理流、合并切片</span></span><br><span class="line">router.<span class="title function_">post</span>(<span class="string">&#x27;/mergeChunks&#x27;</span>, <span class="keyword">async</span> (ctx) =&gt; &#123; </span><br><span class="line">    <span class="keyword">const</span> &#123; filename, size &#125; = ctx.<span class="property">request</span>.<span class="property">body</span>;  </span><br><span class="line">    <span class="keyword">let</span> filePath = path.<span class="title function_">join</span>(outputPath, <span class="string">&#x27;_&#x27;</span> + filename);</span><br><span class="line">    <span class="keyword">await</span> <span class="title function_">mergeFileChunk</span>(filePath, filename, size);</span><br><span class="line">    ctx.<span class="title function_">set</span>(<span class="string">&quot;Content-Type&quot;</span>, <span class="string">&quot;application/json&quot;</span>); </span><br><span class="line">    ctx.<span class="property">body</span> = <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123; </span><br><span class="line">        <span class="attr">data</span>: &#123;<span class="attr">code</span>: <span class="number">2000</span>, filename, size&#125;,  </span><br><span class="line">        <span class="attr">message</span>: <span class="string">&#x27;merge chunks successful！&#x27;</span> </span><br><span class="line">    &#125;);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">pipeStream</span> = (<span class="params">path, writeStream</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function"><span class="params">resolve</span> =&gt;</span> &#123;  </span><br><span class="line">        <span class="keyword">const</span> readStream = fs.<span class="title function_">createReadStream</span>(path);  </span><br><span class="line">        readStream.<span class="title function_">pipe</span>(writeStream);   </span><br><span class="line">        readStream.<span class="title function_">on</span>(<span class="string">&quot;end&quot;</span>, <span class="function">() =&gt;</span> &#123;   </span><br><span class="line">            fs.<span class="title function_">unlinkSync</span>(path);    </span><br><span class="line">            <span class="title function_">resolve</span>();  </span><br><span class="line">        &#125;); </span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">mergeFileChunk</span> = <span class="keyword">async</span> (<span class="params">filePath, filename, size</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">const</span> chunkDir = path.<span class="title function_">join</span>(outputPath, filename); </span><br><span class="line">    <span class="keyword">const</span> chunkPaths = fs.<span class="title function_">readdirSync</span>(chunkDir); </span><br><span class="line">    <span class="keyword">if</span> (!chunkPaths.<span class="property">length</span>) <span class="keyword">return</span>;  </span><br><span class="line">    <span class="comment">// 根据切片下标进行排序，否则直接读取目录获得的顺序可能会错乱 </span></span><br><span class="line">    chunkPaths.<span class="title function_">sort</span>(<span class="function">(<span class="params">a, b</span>) =&gt;</span> a.<span class="title function_">split</span>(<span class="string">&quot;-&quot;</span>)[<span class="number">1</span>] - b.<span class="title function_">split</span>(<span class="string">&quot;-&quot;</span>)[<span class="number">1</span>]);</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;chunkPaths = &quot;</span>, chunkPaths); </span><br><span class="line">    <span class="keyword">await</span> <span class="title class_">Promise</span>.<span class="title function_">all</span>(chunkPaths.<span class="title function_">map</span>(<span class="function">(<span class="params">cPath, i</span>) =&gt;</span> <span class="title function_">pipeStream</span>(     </span><br><span class="line">        path.<span class="title function_">resolve</span>(chunkDir, cPath),  </span><br><span class="line">        fs.<span class="title function_">createWriteStream</span>(filePath, &#123;   </span><br><span class="line">            <span class="attr">start</span>: i * size,      </span><br><span class="line">            <span class="attr">end</span>: (i + <span class="number">1</span>) * size    </span><br><span class="line">        &#125;)   </span><br><span class="line">    ))); </span><br><span class="line">    fs.<span class="title function_">rmdirSync</span>(chunkDir);  <span class="comment">// 合并后删除保存切片的目录</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> 3、断点续传：支持中断请求和接着中断位置继续发送。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 保存每个上传请求的实例对象，用于后期取消对应请求。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 保存已上传的切片信息等，每次上传前校验后重新请求。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 取消请求的几种方式如下：</span></span><br><span class="line"><span class="comment">**/</span> </span><br><span class="line">(<span class="keyword">new</span> <span class="title class_">XMLHttpRequest</span>()).<span class="title function_">abort</span>()       <span class="comment">// 原生 XHR</span></span><br><span class="line">(<span class="keyword">new</span> <span class="title class_">AbortController</span>()).<span class="title function_">abort</span>()        <span class="comment">// fetch</span></span><br><span class="line"><span class="keyword">new</span> <span class="title class_">CancelToken</span>(<span class="keyword">function</span> (<span class="params">cancel</span>) &#123;&#125;)  <span class="comment">// axios</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> 4、秒传：正式发起上传请求时先发起一个携带文件 hash 的检查请求，</span></span><br><span class="line"><span class="comment"> * 服务端如果查询到文件 hash 已存在就直接复用文件资源，不再需要重新上传。</span></span><br><span class="line"><span class="comment">**/</span> </span><br></pre></td></tr></table></figure>


<h1 id="三、uniapp-在线预览"><a href="#三、uniapp-在线预览" class="headerlink" title="三、uniapp 在线预览"></a>三、uniapp 在线预览</h1><blockquote>
<p>业务系统开发时大多遇到 PDF、Word、Excel、PPT、图片等文件在线预览的需求，而在线预览不是下载后再用本地软件或浏览器打开预览，而是直接通过文件流的形式查看。</p>
</blockquote>
<h2 id="PDF"><a href="#PDF" class="headerlink" title="PDF"></a>PDF</h2><blockquote>
<p><a target="_blank" rel="external nofollow noopener noreferrer" href="https://mozilla.github.io/pdf.js/getting_started/#download">pdf.js 下载</a>解压并后将 build、web 目录拷贝到项目 hybrid&#x2F;html。</p>
</blockquote>
  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">/*</span><br><span class="line"> * @title file-preview.vue</span><br><span class="line"> * </span><br><span class="line"> * @desp  fileUrl：部署在服务器的文件流访问地址</span><br><span class="line"> * @desp  web/viewer.html：插件解压后包含的文件</span><br><span class="line"> * @desp  web/viewer.js：注释代码行 not match</span><br><span class="line"> throw new Error(&#x27;file origin does not match viewer\&#x27;s&#x27;)</span><br><span class="line">**/ </span><br><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">view</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">web-view</span> <span class="attr">:src</span>=<span class="string">&quot;allUrl&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">web-view</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">view</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">import</span> config <span class="keyword">from</span> <span class="string">&#x27;@/config&#x27;</span></span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="attr">allUrl</span>: <span class="string">&#x27;&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">              <span class="attr">viewUrl</span>: <span class="string">&#x27;/hybrid/html/web/viewer.html&#x27;</span></span></span><br><span class="line"><span class="language-javascript">          &#125;</span></span><br><span class="line"><span class="language-javascript">      &#125;,</span></span><br><span class="line"><span class="language-javascript">      <span class="title function_">onLoad</span>(<span class="params">options</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">// fileUrl：文件流访问地址</span></span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">let</span> fileUrl = <span class="built_in">encodeURIComponent</span>(options.<span class="property">url</span>)</span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="property">allUrl</span> = <span class="variable language_">this</span>.<span class="property">viewUrl</span> + <span class="string">&#x27;?file=&#x27;</span> + fileUrl</span></span><br><span class="line"><span class="language-javascript">      &#125;</span></span><br><span class="line"><span class="language-javascript">    &#125;</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="Office"><a href="#Office" class="headerlink" title="Office"></a>Office</h2><blockquote>
<p>首先通过 <a target="_blank" rel="external nofollow noopener noreferrer" href="https://sourceforge.net/projects/openofficeorg.mirror/files/">Apache_OpenOffice</a> 搭建 OpenOffice 服务，然后将 Doc、Word、Excel、PPT 等文件转换为 pdf 后通过 pdf.js 实现预览。</p>
</blockquote>
  <figure class="highlight py"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">// 搭建 openOffice 服务</span><br><span class="line"></span><br><span class="line">// <span class="number">1</span>、Apache_OpenOffice 下载后解压</span><br><span class="line">tar xzvfm Apache_OpenOffice_xxx.tar.gz</span><br><span class="line">cd zh-CN/RPMS</span><br><span class="line">rpm -ivh *rpm</span><br><span class="line"></span><br><span class="line">// <span class="number">2</span>、运行服务</span><br><span class="line"><span class="comment"># 127.0.0.1 只能本机使用该</span></span><br><span class="line">/opt/openoffice4/program/soffice <span class="string">&quot;-accept=socket,host=127.0.0.1,</span></span><br><span class="line"><span class="string">port=8100;urp;&quot;</span> -headless -nofirststartwizard &amp;</span><br><span class="line"><span class="comment"># 0.0.0.0 远程 ip 能使用</span></span><br><span class="line">/opt/openoffice4/program/soffice <span class="string">&quot;-accept=socket,host=0.0.0.0,</span></span><br><span class="line"><span class="string">port=8100;urp;&quot;</span> -headless -nofirststartwizard &amp;</span><br></pre></td></tr></table></figure>

  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br></pre></td><td class="code"><pre><span class="line">// 集成 java</span><br><span class="line"></span><br><span class="line">// 1、pom.xml 添加 jar 包</span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.openoffice<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>juh<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.1.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.openoffice<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jurt<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.1.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.openoffice<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>ridl<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.1.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.openoffice<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>unoil<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.1.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.artofsolving<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jodconverter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.2.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">// 2、jodconverter 2.2.2 下载后单独导入</span><br><span class="line">https://sourceforge.net/projects/jodconverter/files/) </span><br><span class="line"></span><br><span class="line">mvn install:install-file -Dfile=&quot;jodconverter-2.2.2.jar&quot; -DgroupId=com.</span><br><span class="line">artofsolving -DartifactId=jodconverter -Dversion=2.2.2 -Dpackaging=jar</span><br><span class="line"></span><br><span class="line">// 3、通过 openOffice 将文件转换为 pdf</span><br><span class="line">if (&quot;DOC&quot;.equals(ext) || &quot;DOCX&quot;.equals(ext) || &quot;XLS&quot;.equals(ext) || </span><br><span class="line">&quot;XLSX&quot;.equals(ext) || &quot;PPT&quot;.equals(ext) || &quot;PPTX&quot;.equals(ext)) &#123;</span><br><span class="line">    // 转换文件名：filePath 在数据库中不带文件后缀，jodConverter 必须识别后缀</span><br><span class="line">    String filePath = sourceFile.getPath();</span><br><span class="line">    File pdfFile;</span><br><span class="line">    if (filePath.contains(&quot;.&quot;)) &#123;</span><br><span class="line">        pdfFile = new File(filePath.substring(0, filePath.lastIndexOf(&quot;.&quot;)) + &quot;.pdf&quot;);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        pdfFile = new File(filePath + &quot;.pdf&quot;);</span><br><span class="line">    &#125;</span><br><span class="line">    // 不存在的文件直接报错</span><br><span class="line">    if (!sourceFile.exists()) &#123;</span><br><span class="line">        log.info(&quot;需要预览的文档在服务器中不存在!!!&quot;);</span><br><span class="line">        return;</span><br><span class="line">    &#125;</span><br><span class="line">    // 如果文件已经转换过则直接预览</span><br><span class="line">    if (pdfFile.exists()) &#123;</span><br><span class="line">        sourceFile = pdfFile;</span><br><span class="line">        response.setContentType(&quot;application/pdf&quot;);</span><br><span class="line">        return;</span><br><span class="line">    &#125;</span><br><span class="line">    // 打开 OpenOffice 连接开始转换</span><br><span class="line">    OpenOfficeConnection connection;</span><br><span class="line">    try &#123;</span><br><span class="line">        connection = new SocketOpenOfficeConnection(openofficeHost, openofficePort);</span><br><span class="line">        connection.connect();</span><br><span class="line"></span><br><span class="line">    &#125; catch (java.net.ConnectException e) &#123;</span><br><span class="line">        log.warn(&quot;openOffice未连接，正在重新连接...&quot;);</span><br><span class="line">        String command = openofficeInstallPath + &quot;program/soffice -headless -accept</span><br><span class="line">        =\&quot;socket,host=127.0.0.1,port=8100;urp;\&quot; -nofirststartwizard&quot;;</span><br><span class="line">        Runtime.getRuntime().exec(command);</span><br><span class="line"></span><br><span class="line">        Thread.sleep(1000);</span><br><span class="line">        connection = new SocketOpenOfficeConnection(8100);</span><br><span class="line">        connection.connect();</span><br><span class="line">        log.warn(&quot;openOffice 重新连接成功!!!&quot;);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    try &#123;</span><br><span class="line">        DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection);</span><br><span class="line">        converter.convert(sourceFile, pdfFile);</span><br><span class="line">        connection.disconnect();</span><br><span class="line"></span><br><span class="line">        sourceFile = pdfFile;</span><br><span class="line">        response.setContentType(&quot;application/pdf&quot;);</span><br><span class="line">    &#125; catch (OpenOfficeException e) &#123;</span><br><span class="line">        e.printStackTrace();</span><br><span class="line">        log.info(&quot;读取转换文件失败!!!&quot;);</span><br><span class="line">    &#125; finally &#123;</span><br><span class="line">        try &#123;</span><br><span class="line">            if (connection != null) &#123;</span><br><span class="line">                connection.disconnect();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; catch (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="Image"><a href="#Image" class="headerlink" title="Image"></a>Image</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 前端预览</span></span><br><span class="line">uni.<span class="title function_">previewImage</span>(&#123;</span><br><span class="line">    <span class="attr">current</span>: <span class="number">0</span>,              <span class="comment">// 预览的图片索引</span></span><br><span class="line">    <span class="attr">urls</span>: [<span class="string">&#x27;文件流访问地址&#x27;</span>],  <span class="comment">// 预览的图片链接列表</span></span><br><span class="line">    <span class="attr">longPressActions</span>: &#123;      <span class="comment">// 长按图片显示操作菜单，默认为保存相册</span></span><br><span class="line">        <span class="attr">itemList</span>: [<span class="string">&#x27;发送给朋友&#x27;</span>, <span class="string">&#x27;保存图片&#x27;</span>, <span class="string">&#x27;收藏&#x27;</span>],   <span class="comment">// 按钮数组</span></span><br><span class="line">        <span class="attr">success</span>: <span class="keyword">function</span>(<span class="params">data</span>) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;选中图片&#x27;</span>, data.<span class="property">index</span> + <span class="number">1</span>);</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;选中按钮&#x27;</span>, data.<span class="property">tapIndex</span> + <span class="number">1</span>);</span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="attr">fail</span>: <span class="keyword">function</span>(<span class="params">err</span>) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">error</span>(err.<span class="property">errMsg</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 后端文件流：根据文件后缀对应的不同类型进行预览 </span></span><br><span class="line"><span class="title class_">String</span> ext = <span class="string">&quot;&quot;</span>;</span><br><span class="line"><span class="keyword">if</span> (!<span class="string">&quot;&quot;</span>.<span class="title function_">equals</span>(url) &amp;&amp; url.<span class="title function_">contains</span>(<span class="string">&quot;.&quot;</span>)) &#123;</span><br><span class="line">    ext= url.<span class="title function_">substring</span>(url.<span class="title function_">lastIndexOf</span>(<span class="string">&quot;.&quot;</span>)+<span class="number">1</span>,url.<span class="title function_">length</span>()).<span class="title function_">toUpperCase</span>();</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (<span class="string">&quot;PNG&quot;</span>.<span class="title function_">equals</span>(ext) || <span class="string">&quot;JPEG&quot;</span>.<span class="title function_">equals</span>(ext) || <span class="string">&quot;JPG&quot;</span>.<span class="title function_">equals</span>(ext)) &#123;</span><br><span class="line">    response.<span class="title function_">setContentType</span>(<span class="string">&quot;image/jpeg&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (<span class="string">&quot;BMP&quot;</span>.<span class="title function_">equals</span>(ext)) &#123;</span><br><span class="line">    response.<span class="title function_">setContentType</span>(<span class="string">&quot;image/bmp&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (<span class="string">&quot;GIF&quot;</span>.<span class="title function_">equals</span>(ext)) &#123;</span><br><span class="line">    response.<span class="title function_">setContentType</span>(<span class="string">&quot;image/gif&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (<span class="string">&quot;PDF&quot;</span>.<span class="title function_">equals</span>(ext)) &#123;</span><br><span class="line">    response.<span class="title function_">setContentType</span>(<span class="string">&quot;application/pdf&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="Docx-1"><a href="#Docx-1" class="headerlink" title="Docx"></a>Docx</h2><blockquote>
<p>以上方案只能实现简单的文档预览，加水印、防复制、在线编辑等复杂需求则需要使用永中云服务平台、金山WPS开放平台、腾讯文档开放API等。准备工作有：<a target="_blank" rel="external nofollow noopener noreferrer" href="https://open.yozocloud.cn/">永中云服务</a>注册、登录、根据文档进行开发者申请、管理中心申请云预览等应用、应用列表查看 APPID APPKEY。</p>
</blockquote>
  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">// 开源项目</span><br><span class="line">https://gitee.com/twofloor/uniapp-admin</span><br><span class="line">https://gitee.com/twofloor/uniapp-file-upload</span><br><span class="line"></span><br><span class="line">// preview.vue</span><br><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">view</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">web-view</span> <span class="attr">v-if</span>=<span class="string">&quot;yzPreviewUrl&quot;</span> <span class="attr">:src</span>=<span class="string">&quot;yzPreviewUrl&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">web-view</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">view</span> <span class="attr">v-else</span>&gt;</span>文档地址无效，无法加载该文档<span class="tag">&lt;/<span class="name">view</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">view</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">import</span> config <span class="keyword">from</span> <span class="string">&#x27;@/config&#x27;</span></span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> &#123; <span class="attr">yzPreviewUrl</span>: <span class="string">&#x27;&#x27;</span> &#125;</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">onLoad</span>(<span class="params">option</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">// 文档上传后跳转到当前预览页面</span></span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">if</span> (option.<span class="property">fileData</span>) &#123; <span class="keyword">return</span> &#125;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">const</span> d = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(<span class="built_in">decodeURIComponent</span>(option.<span class="property">fileData</span>))</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">yzPreviewUrl</span> = <span class="string">&#x27;http://eic.yozocloud.cn/api/view/file&#x27;</span> + </span></span><br><span class="line"><span class="language-javascript">            <span class="string">&#x27;?fileVersionId=&#x27;</span> + d.<span class="property">fileVersionId</span> + <span class="string">&#x27;&amp;appId=&#x27;</span> + config.<span class="property">APPID</span></span></span><br><span class="line"><span class="language-javascript">        &#125;</span></span><br><span class="line"><span class="language-javascript">    &#125;</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>



<h1 id="四、uniapp-文件上传"><a href="#四、uniapp-文件上传" class="headerlink" title="四、uniapp 文件上传"></a>四、uniapp 文件上传</h1><blockquote>
<p>uni-app 项目为例实现上传包括图片和视频的所有目录文件并同时支持 Android、IOS。主要实现思路如下：uni-app 没有提供文件上传组件并且不支持 input type&#x3D;”file”、uni-app App 内置 HTML5+ 引擎并提供 plus 接口，可以直接调用 Android 系统函数来打开系统目录，IOS 则没有找到方法但可以通过直接嵌入 H5 页面实现。</p>
</blockquote>
<h2 id="图片上传"><a href="#图片上传" class="headerlink" title="图片上传"></a>图片上传</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">uploadImg</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> that = <span class="variable language_">this</span>;</span><br><span class="line">    uni.<span class="title function_">chooseImage</span>(&#123;</span><br><span class="line">        <span class="attr">count</span>: <span class="number">3</span>,</span><br><span class="line">        <span class="attr">sizeType</span>: [<span class="string">&quot;original&quot;</span>, <span class="string">&quot;compressed&quot;</span>],</span><br><span class="line">        <span class="attr">sourceType</span>: [<span class="string">&quot;album&quot;</span>, <span class="string">&quot;camera&quot;</span>],</span><br><span class="line">        <span class="attr">success</span>: <span class="function">(<span class="params">res</span>) =&gt;</span> &#123;</span><br><span class="line">            <span class="comment">// tempFilePaths：数组的元素是字符串，临时本地图片路径</span></span><br><span class="line">            <span class="comment">// tempFiles：数组元素是字典对象，临时路径 path 和图片大小 size。</span></span><br><span class="line">            <span class="keyword">let</span> tempFiles = res.<span class="property">tempFiles</span>;</span><br><span class="line">            <span class="keyword">if</span> (tempFiles.<span class="property">length</span> &gt; <span class="number">3</span>) &#123;</span><br><span class="line">                uni.<span class="title function_">showToast</span>(&#123; <span class="attr">icon</span>: <span class="string">&#x27;none&#x27;</span>, <span class="attr">title</span>: <span class="string">&#x27;最多上传 3 张图片&#x27;</span> &#125;)</span><br><span class="line">                <span class="keyword">return</span></span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">let</span> <span class="title class_">ImgList</span> = tempFiles.<span class="title function_">map</span>(<span class="function"><span class="params">item</span>=&gt;</span>&#123;<span class="attr">name</span>:item.<span class="property">path</span>, <span class="attr">uri</span>:item&#125;)</span><br><span class="line">            uni.<span class="title function_">showLoading</span>(&#123; <span class="attr">mask</span>: <span class="literal">true</span>, <span class="attr">title</span>: <span class="string">&#x27;上传中...&#x27;</span> &#125;);</span><br><span class="line">            uni.<span class="title function_">uploadFile</span>(&#123;</span><br><span class="line">                <span class="attr">name</span>: <span class="string">&#x27;file&#x27;</span>,        </span><br><span class="line">                <span class="attr">fileType</span>: <span class="string">&#x27;image&#x27;</span>,</span><br><span class="line">                <span class="attr">files</span>: <span class="title class_">ImgList</span>,</span><br><span class="line">                <span class="attr">url</span>: that.<span class="property">base_url</span> + <span class="string">&#x27;api/imgUpload&#x27;</span>,</span><br><span class="line">                <span class="attr">header</span>: &#123; <span class="attr">token</span>: uni.<span class="title function_">getStorageSync</span>(<span class="string">&#x27;token&#x27;</span>) &#125;,</span><br><span class="line">                <span class="title function_">success</span>(<span class="params">res</span>) &#123;</span><br><span class="line">                    uni.<span class="title function_">hideLoading</span>();</span><br><span class="line">                    <span class="keyword">let</span> result = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(res.<span class="property">data</span>)</span><br><span class="line">                    that.<span class="property">ImgList</span> = result.<span class="property">data</span>.<span class="title function_">map</span>(<span class="function"><span class="params">item</span> =&gt;</span> item.<span class="property">newFile</span>)</span><br><span class="line">                &#125;,</span><br><span class="line">                <span class="attr">fail</span>: <span class="keyword">function</span> (<span class="params">err</span>) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (!err) &#123; <span class="keyword">return</span> &#125;</span><br><span class="line">                    uni.<span class="title function_">showModal</span>(&#123; <span class="attr">title</span>: <span class="string">&#x27;失败&#x27;</span>, <span class="attr">showCancel</span>: <span class="literal">false</span> &#125;);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;,</span><br><span class="line"><span class="title function_">previewImg</span>(<span class="params">index</span>) &#123;</span><br><span class="line">    uni.<span class="title function_">previewImage</span>(&#123; <span class="attr">current</span>: index, <span class="attr">urls</span>: <span class="variable language_">this</span>.<span class="property">ImgList</span>, <span class="attr">loop</span>: <span class="literal">true</span> &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="视频上传"><a href="#视频上传" class="headerlink" title="视频上传"></a>视频上传</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">uploadVideo</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> that = <span class="variable language_">this</span>;</span><br><span class="line">    uni.<span class="title function_">chooseVideo</span>(&#123;</span><br><span class="line">        <span class="attr">maxDuration</span>: <span class="number">60</span>,   <span class="comment">// 最大 60s</span></span><br><span class="line">        <span class="attr">count</span>: <span class="number">1</span>,</span><br><span class="line">        <span class="attr">compressed</span>: <span class="literal">true</span>,</span><br><span class="line">        <span class="attr">camera</span>: <span class="string">&#x27;front&#x27;</span>,   <span class="comment">// 默认 back</span></span><br><span class="line">        <span class="attr">sourceType</span>: [<span class="string">&quot;album&quot;</span>, <span class="string">&quot;camera&quot;</span>],</span><br><span class="line">        <span class="attr">success</span>: <span class="function">(<span class="params">res</span>) =&gt;</span> &#123;</span><br><span class="line">            uni.<span class="title function_">showLoading</span>(&#123; <span class="attr">mask</span>: <span class="literal">true</span>, <span class="attr">title</span>: <span class="string">&quot;上传中...&quot;</span> &#125;);</span><br><span class="line">            uni.<span class="title function_">uploadFile</span>(&#123;</span><br><span class="line">                <span class="attr">url</span>: that.<span class="property">base_url</span> + <span class="string">&#x27;api/videoUpload&#x27;</span>,</span><br><span class="line">                <span class="attr">filePath</span>: res.<span class="property">tempFilePaths</span>[<span class="number">0</span>],</span><br><span class="line">                <span class="attr">name</span>: <span class="string">&quot;file&quot;</span>,</span><br><span class="line">                <span class="attr">fileType</span>: <span class="string">&quot;video&quot;</span>,</span><br><span class="line">                <span class="attr">header</span>: &#123; <span class="attr">token</span>: uni.<span class="title function_">getStorageSync</span>(<span class="string">&#x27;token&#x27;</span>) &#125;,</span><br><span class="line">                <span class="title function_">success</span>(<span class="params">res</span>) &#123;</span><br><span class="line">                    uni.<span class="title function_">hideLoading</span>();</span><br><span class="line">                    <span class="keyword">let</span> result = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(res.<span class="property">data</span>)</span><br><span class="line">                    that.<span class="title function_">videoCompress</span>(result.<span class="property">data</span>[<span class="number">0</span>].<span class="property">newFile</span>)</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;,</span><br><span class="line">videoCompress (tempFilePath) &#123;</span><br><span class="line">    <span class="keyword">let</span> that = <span class="variable language_">this</span>;</span><br><span class="line">    uni.<span class="title function_">compressVideo</span>(&#123;</span><br><span class="line">        <span class="attr">quality</span>: <span class="string">&quot;low&quot;</span>,     <span class="comment">// medium、high</span></span><br><span class="line">        <span class="attr">src</span>: tempFilePath,</span><br><span class="line">        <span class="attr">success</span>: <span class="keyword">function</span> (<span class="params">res</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (res.<span class="property">size</span> &gt; <span class="number">1025</span> * <span class="number">1024</span> * <span class="number">10</span>) &#123;</span><br><span class="line">                that.<span class="title function_">videoCompress</span>(res.<span class="property">tempFilePath</span>)</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                that.<span class="property">videoSrc</span> = res.<span class="property">tempFilePath</span></span><br><span class="line">            &#125;</span><br><span class="line">            </span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="attr">fail</span>: <span class="keyword">function</span> (<span class="params">err</span>) &#123;</span><br><span class="line">            uni.<span class="title function_">showToast</span>(&#123; <span class="attr">title</span>: <span class="string">&quot;压缩失败&quot;</span>, <span class="attr">icon</span>: <span class="string">&quot;none&quot;</span> &#125;);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="文档上传"><a href="#文档上传" class="headerlink" title="文档上传"></a>文档上传</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 以七牛存储为例，将七牛上传地址和 token 配置后即可</span></span><br><span class="line">uni.<span class="title function_">chooseFile</span>(&#123;</span><br><span class="line">    <span class="attr">count</span>: <span class="number">1</span>,</span><br><span class="line">    <span class="attr">extension</span>: [<span class="string">&#x27;doc&#x27;</span>, <span class="string">&#x27;xlsx&#x27;</span>, <span class="string">&#x27;ppt&#x27;</span>, <span class="string">&#x27;rar&#x27;</span>, <span class="string">&#x27;zip&#x27;</span>],</span><br><span class="line">    <span class="attr">success</span>: <span class="keyword">function</span> (<span class="params">res</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (res.<span class="property">size</span> &gt; <span class="number">30</span> * <span class="number">1024</span> * <span class="number">1024</span>) &#123;</span><br><span class="line">            uni.<span class="title function_">showToast</span>(&#123; <span class="attr">icon</span>: <span class="string">&#x27;none&#x27;</span>, <span class="attr">title</span>: <span class="string">&#x27;附件大小不能超过 30M&#x27;</span> &#125;)</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;   </span><br><span class="line">        uni.<span class="title function_">uploadFile</span>(&#123;</span><br><span class="line">            <span class="attr">name</span>: <span class="string">&quot;file&quot;</span>,</span><br><span class="line">            <span class="attr">filePath</span>: res.<span class="property">tempFilePaths</span>[<span class="number">0</span>], <span class="comment">// 临时地址</span></span><br><span class="line">            <span class="attr">url</span>: <span class="string">&#x27;七牛上传地址&#x27;</span>,</span><br><span class="line">            <span class="attr">formData</span>: &#123; <span class="attr">token</span>: <span class="string">&#x27;七牛 token&#x27;</span> &#125;,</span><br><span class="line">            <span class="attr">success</span>: <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">                uni.<span class="title function_">showModal</span>(&#123; <span class="attr">title</span>: <span class="string">&#x27;成功&#x27;</span>, <span class="attr">showCancel</span>: <span class="literal">false</span> &#125;);</span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="attr">fail</span>: <span class="keyword">function</span>(<span class="params">err</span>) &#123;</span><br><span class="line">                <span class="keyword">if</span> (!err) &#123; <span class="keyword">return</span> &#125;</span><br><span class="line">                uni.<span class="title function_">showModal</span>(&#123; <span class="attr">title</span>: <span class="string">&#x27;失败&#x27;</span>, <span class="attr">showCancel</span>: <span class="literal">false</span> &#125;);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);      </span><br></pre></td></tr></table></figure>

<h2 id="目录文件上传"><a href="#目录文件上传" class="headerlink" title="目录文件上传"></a>目录文件上传</h2><blockquote>
<p>如果需要上传图片等系统目录文件并支持 Android&#x2F;IOS，uni-app 却没有提供文件上传组件而且不支持 <code>input type=&quot;file&quot;</code>，则可基于 WebView 模式内嵌 H5 页面进行二次开发，注意小程序平台 web-view url 需要在后台配置域名白名单。</p>
</blockquote>
  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br></pre></td><td class="code"><pre><span class="line">// fileUpload.vue</span><br><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">view</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">web-view</span> <span class="attr">:src</span>=<span class="string">&quot;&#x27;/hybrid/html/index.html?info=&#x27; + info&quot;</span> </span></span><br><span class="line"><span class="tag">        @<span class="attr">message</span>=<span class="string">&quot;handleMessage&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">web-view</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">view</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">                <span class="attr">info</span>: <span class="built_in">encodeURIComponent</span>(<span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123; </span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">appId</span>: <span class="string">&#x27;名称&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">appKey</span>: <span class="string">&#x27;密钥&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">dmc</span>: <span class="string">&#x27;http://dmc.yozocloud.cn&#x27;</span></span></span><br><span class="line"><span class="language-javascript">                &#125;))</span></span><br><span class="line"><span class="language-javascript">            &#125;</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="title function_">handleMessage</span>(<span class="params">event</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">                <span class="keyword">let</span> msg = <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(event.<span class="property">detail</span>.<span class="property">data</span>)</span></span><br><span class="line"><span class="language-javascript">                <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;h5 发送数据：&#x27;</span>, msg)</span></span><br><span class="line"><span class="language-javascript">            &#125;</span></span><br><span class="line"><span class="language-javascript">        &#125;</span></span><br><span class="line"><span class="language-javascript">    &#125;</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">/*</span><br><span class="line"> * @title index.html</span><br><span class="line"> * </span><br><span class="line"> * @desp  uni 组件通过 web-view 标签来实现内嵌页面</span><br><span class="line"> * @desp  使用时应放到不编译的项目目录 /hybrid/html/</span><br><span class="line"> * @desp  uni-sdk 必须引入，js-sdk 则在不需要兼容小程序时不需要</span><br><span class="line">**/</span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span> <span class="attr">src</span>=<span class="string">&quot;https://res.wx.qq.com/open/js/</span></span></span><br><span class="line"><span class="string"><span class="tag">jweixin-1.4.0.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span> <span class="attr">src</span>=<span class="string">&quot;https://js.cdn.aliyun.dcloud.</span></span></span><br><span class="line"><span class="string"><span class="tag">net.cn/dev/uni-app/uni.webview.1.5.1.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span> <span class="attr">src</span>=<span class="string">&quot;js/h5uploader.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span> <span class="attr">src</span>=<span class="string">&quot;js/signclient.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span>&gt;</span></span><br><span class="line">    var info = getQueryString(&#x27;info&#x27;);</span><br><span class="line">    info = JSON.parse(decodeURIComponent(info))</span><br><span class="line"></span><br><span class="line">    uni.getEnv(function(res) &#123;</span><br><span class="line">        console.log(&#x27;当前环境：&#x27;, JSON.stringify(res))</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">    var btn = document.getElementById(&#x27;upload&#x27;);</span><br><span class="line">    btn.addEventListener(&quot;click&quot;, function(e) &#123;</span><br><span class="line">        H5Uploader.upload(&#123;</span><br><span class="line">            action: info.dmc + &#x27;/api/file/upload?appId=&#x27; + info.appId,</span><br><span class="line">            id: &#x27;fileBtn&#x27;,</span><br><span class="line">            size: &#123;</span><br><span class="line">                max: 50000, </span><br><span class="line">                valide: function(e)&#123; if(e)&#123; alert(e.name+&#x27;超过 5M&#x27;) &#125; &#125;</span><br><span class="line">            &#125;,</span><br><span class="line">            type: &#123;</span><br><span class="line">                name: &#x27;csv;doc;docx;xls;xltx;ppt;pptx;jpeg;jpg;png;gif;</span><br><span class="line">                bmp;tif;rar;zip;uof;uot;uos;uop;pdf;ofd;&#x27;,</span><br><span class="line">                valide: function(e)&#123; if(e)&#123; alert(e.name+&#x27;类型不支持&#x27;) &#125; &#125;</span><br><span class="line">            &#125;,</span><br><span class="line">            progress: function() &#123;</span><br><span class="line">                console.log(&#x27;上传中...&#x27;)</span><br><span class="line">            &#125;,</span><br><span class="line">            success: function(data) &#123;</span><br><span class="line">                var tmpJson = JSON.parse(data)</span><br><span class="line">                tmpJson.sign = generateSign(appKey, &#123;</span><br><span class="line">                    appId: [appId], </span><br><span class="line">                    fileVersionId: [tmpJson.fileVersionId]</span><br><span class="line">                &#125;);</span><br><span class="line">                uni.postMessage(&#123; data:&#123; action: tmpJson &#125; &#125;);</span><br><span class="line">                uni.navigateBack(&#123; delta: 1 &#125;);</span><br><span class="line">            &#125;,</span><br><span class="line">            fail: function(data) &#123;</span><br><span class="line">                alert(&#x27;上传失败&#x27;)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;, false);</span><br><span class="line"></span><br><span class="line">    function getQueryString(key) &#123;</span><br><span class="line">        var reg = new RegExp(&#x27;(^|&amp;)&#x27; + key + &#x27;=([^&amp;]*)(&amp;|$)&#x27;)</span><br><span class="line">        var r = window.location.search.substr(1).match(reg)</span><br><span class="line">        if (r != null) return unescape(r[2])</span><br><span class="line">        return null</span><br><span class="line">    &#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// signclient.js</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">generateSign</span>(<span class="params">secret, params</span>) &#123;</span><br><span class="line">    <span class="keyword">var</span> fullParamStr = <span class="title function_">uniqSortParams</span>(params);</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">hmacSHA256</span>(fullParamStr, secret);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">uniqSortParams</span>(<span class="params">params</span>) &#123;</span><br><span class="line">    <span class="keyword">delete</span> params.<span class="property">sign</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> var5 = [];</span><br><span class="line">    <span class="keyword">var</span> var6 = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">var</span> key <span class="keyword">in</span> params) &#123;</span><br><span class="line">        var5[var6] = key;</span><br><span class="line">        var6++;</span><br><span class="line">    &#125;</span><br><span class="line">    var5.<span class="title function_">sort</span>(<span class="keyword">function</span>(<span class="params">a, b</span>)&#123; <span class="keyword">return</span> a.<span class="title function_">localeCompare</span>(b, <span class="string">&#x27;zh-CN&#x27;</span>) &#125;);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> result = <span class="string">&quot;&quot;</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">var</span> var7 = <span class="number">0</span>; var7 &lt; var5.<span class="property">length</span>; var7++) &#123;</span><br><span class="line">        <span class="keyword">var</span> key = var5[var7];</span><br><span class="line">        <span class="keyword">var</span> var8 = params[key];</span><br><span class="line">        var8.<span class="title function_">sort</span>(<span class="keyword">function</span> (<span class="params">a, b</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> a.<span class="title function_">localeCompare</span>(b, <span class="string">&#x27;zh-CN&#x27;</span>);</span><br><span class="line">        &#125;)</span><br><span class="line">        <span class="keyword">if</span> (var8 != <span class="literal">null</span> &amp;&amp; var8.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">var</span> var9 = <span class="number">0</span>; var9 &lt; var8.<span class="property">length</span>; var9++) &#123;</span><br><span class="line">                result += key + <span class="string">&quot;=&quot;</span> + var8[var9];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            result += key + <span class="string">&quot;=&quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">hmacSHA256</span>(<span class="params">data, key</span>) &#123;</span><br><span class="line">    data != <span class="literal">null</span> ? data : <span class="string">&quot;&quot;</span>;</span><br><span class="line">    <span class="keyword">var</span> var2 = <span class="title class_">CryptoJS</span>.<span class="title class_">HmacSHA256</span>(data, key);</span><br><span class="line">    <span class="keyword">var</span> var3 = var2.<span class="title function_">toString</span>(<span class="title class_">CryptoJS</span>.<span class="property">enc</span>.<span class="property">Hex</span>);</span><br><span class="line">    <span class="keyword">return</span> var3.<span class="title function_">toUpperCase</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// h5uploader.js</span></span><br><span class="line">(<span class="keyword">function</span>(<span class="params"><span class="variable language_">window</span></span>) &#123;</span><br><span class="line"></span><br><span class="line">  <span class="variable language_">window</span>.<span class="property">H5Uploader</span> = (<span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">function</span> <span class="title function_">createXhr</span>(<span class="params"></span>) &#123;</span><br><span class="line">      <span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="title class_">XMLHttpRequest</span> != <span class="string">&quot;undefined&quot;</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">XMLHttpRequest</span>();</span><br><span class="line">      &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="title class_">ActiveXObject</span> != <span class="string">&quot;undefined&quot;</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="variable language_">arguments</span>.<span class="property">callee</span>.<span class="property">activeXString</span> != <span class="string">&quot;string&quot;</span>) &#123;</span><br><span class="line">          <span class="keyword">var</span> versions = [<span class="string">&quot;MSXML2.XMLHttp.6.0&quot;</span>, <span class="string">&quot;MSXML2.XMLHttp.3.0&quot;</span>, </span><br><span class="line">          <span class="string">&quot;MSXML2.XMLHttp&quot;</span>];</span><br><span class="line">          <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>, len = versions.<span class="property">length</span>; i &lt; len; i++) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">              <span class="keyword">new</span> <span class="title class_">ActiveXObject</span>(versions[i]);</span><br><span class="line">              <span class="variable language_">arguments</span>.<span class="property">callee</span>.<span class="property">activeXString</span> = versions[i];</span><br><span class="line">              <span class="keyword">break</span>;</span><br><span class="line">            &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">              <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&#x27;Create XHR ActiveXObject error.&#x27;</span> + e);</span><br><span class="line">            &#125;</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ActiveXObject</span>(<span class="variable language_">arguments</span>.<span class="property">callee</span>.<span class="property">activeXString</span>);</span><br><span class="line">      &#125; <span class="keyword">else</span> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&#x27;No XHR object avaliable.&#x27;</span> + e);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      <span class="attr">upload</span>: <span class="keyword">function</span>(<span class="params">literals</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="title class_">Object</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">toString</span>.<span class="title function_">call</span>(literals)!=<span class="string">&#x27;[object Array]&#x27;</span>)&#123;</span><br><span class="line">          <span class="variable language_">this</span>.<span class="title function_">handUpload</span>(literals);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">          <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; literals.<span class="property">length</span>; i++) &#123;</span><br><span class="line">            <span class="variable language_">this</span>.<span class="title function_">handUpload</span>(literals[i]);</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;,</span><br><span class="line"></span><br><span class="line">      <span class="attr">handUpload</span>: <span class="keyword">function</span>(<span class="params">literals</span>) &#123;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (literals.<span class="property">action</span> === <span class="literal">undefined</span>) &#123;</span><br><span class="line">          <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&#x27;upload action address option is undefined.&#x27;</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">var</span> xhr = <span class="title function_">createXhr</span>();</span><br><span class="line">        xhr.<span class="title function_">open</span>(<span class="string">&quot;POST&quot;</span>, literals.<span class="property">action</span>, <span class="literal">true</span>);</span><br><span class="line">        <span class="comment">// xhr.setRequestHeader(&quot;Content-Type&quot;, &quot;multipart/form-data&quot;);</span></span><br><span class="line">        <span class="comment">// xhr.setRequestHeader(&quot;X-Requested-With&quot;, &quot;XMLHttpRequest&quot;);</span></span><br><span class="line">        xhr.<span class="property">onreadystatechange</span> = <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (xhr.<span class="property">readyState</span> != <span class="number">4</span>) &#123; <span class="keyword">return</span> &#125;</span><br><span class="line">            <span class="keyword">var</span> body = xhr.<span class="property">responseText</span>;</span><br><span class="line">            <span class="keyword">if</span> ( xhr.<span class="property">status</span>==<span class="number">200</span> &amp;&amp; literals.<span class="property">success</span>) &#123;</span><br><span class="line">                literals.<span class="title function_">success</span>(body);</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (literals) &#123;</span><br><span class="line">                literals.<span class="title function_">fail</span>(body);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">if</span> (!literals.<span class="property">id</span>) &#123;</span><br><span class="line">          <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&#x27;The file id option is undefined.&#x27;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">var</span> data = <span class="keyword">new</span> <span class="title class_">FormData</span>();</span><br><span class="line">        <span class="keyword">var</span> file = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(literals.<span class="property">id</span>);</span><br><span class="line">        <span class="keyword">if</span> (!file) &#123;</span><br><span class="line">          <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&#x27;file element is undefined:&#x27;</span> + literals.<span class="property">id</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">var</span> name = file.<span class="title function_">getAttribute</span>(<span class="string">&#x27;name&#x27;</span>);</span><br><span class="line">        <span class="keyword">if</span> (!name) &#123;</span><br><span class="line">          <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&#x27;file input name is undefined.&#x27;</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (literals.<span class="property">size</span>) &#123;   <span class="comment">// Check file Size</span></span><br><span class="line">          <span class="keyword">var</span> evt = <span class="variable language_">this</span>.<span class="title function_">checkSize</span>(file.<span class="property">files</span>, literals.<span class="property">size</span>.<span class="property">max</span>);</span><br><span class="line">          <span class="keyword">if</span> (evt) &#123;</span><br><span class="line">            <span class="keyword">if</span> (literals.<span class="property">size</span>.<span class="property">valide</span>) literals.<span class="property">size</span>.<span class="title function_">valide</span>(evt);</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&#x27;file size exceed max value.&#x27;</span>);</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (literals.<span class="property">type</span>) &#123;   <span class="comment">// Check file type</span></span><br><span class="line">          <span class="keyword">var</span> evt1 = <span class="variable language_">this</span>.<span class="title function_">checkType</span>(file.<span class="property">files</span>, literals.<span class="property">type</span>.<span class="property">name</span>);</span><br><span class="line">          <span class="keyword">if</span> (evt1) &#123;</span><br><span class="line">            <span class="keyword">if</span> (literals.<span class="property">type</span>.<span class="property">valide</span>) literals.<span class="property">type</span>.<span class="title function_">valide</span>(evt1);</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&#x27;file type is error.&#x27;</span>);</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (literals.<span class="property">progress</span>) &#123;   <span class="comment">// Progress</span></span><br><span class="line">          literals.<span class="title function_">progress</span>();</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; file.<span class="property">files</span>.<span class="property">length</span>; i++) &#123;</span><br><span class="line">          data.<span class="title function_">append</span>(name, file.<span class="property">files</span>[i]);</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">          xhr.<span class="title function_">send</span>(data);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">          <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(e);</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;,</span><br><span class="line"></span><br><span class="line">      <span class="comment">// Validate file size</span></span><br><span class="line">      <span class="attr">checkSize</span>: <span class="keyword">function</span>(<span class="params">file, size</span>) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; file.<span class="property">length</span>; i++) &#123;</span><br><span class="line">          <span class="keyword">if</span> (file[i].<span class="property">size</span> &gt; size * <span class="number">1024</span>) &#123; <span class="comment">// bytes</span></span><br><span class="line">            <span class="keyword">return</span> file[i];</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;,</span><br><span class="line"></span><br><span class="line">      <span class="comment">// Validate file type</span></span><br><span class="line">      <span class="attr">checkType</span>: <span class="keyword">function</span>(<span class="params">file, type</span>) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; file.<span class="property">length</span>; i++) &#123;</span><br><span class="line">          <span class="keyword">var</span> arr = file[i].<span class="property">name</span>.<span class="title function_">split</span>(<span class="string">&quot;.&quot;</span>);</span><br><span class="line">          <span class="keyword">if</span> (type.<span class="title function_">indexOf</span>(arr[arr.<span class="property">length</span> - <span class="number">1</span>]) === -<span class="number">1</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> file[i];</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;)();</span><br><span class="line"></span><br><span class="line">&#125;)(<span class="variable language_">window</span>);</span><br></pre></td></tr></table></figure>


<h1 id="五、minio-文件管理"><a href="#五、minio-文件管理" class="headerlink" title="五、minio 文件管理"></a>五、minio 文件管理</h1><blockquote>
<p>一个基于 Apache License v2.0 开源协议的对象存储服务，用来存放管理文件的文件服务器。它兼容亚马逊S3云存储服务接口并支持多种语言客户端集成开发，非常适合于存储大容量非结构化的数据，例如图片、视频、日志文件、备份数据和容器&#x2F;虚拟机镜像等。</p>
</blockquote>
<h2 id="Node-项目集成"><a href="#Node-项目集成" class="headerlink" title="Node 项目集成"></a>Node 项目集成</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// minio.js：需要先安装 npm i minio --save-dev</span></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">Minio</span> = <span class="built_in">require</span>(<span class="string">&#x27;minio&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> config = <span class="built_in">require</span>(<span class="string">&#x27;../../../config/config&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> entityFun = <span class="built_in">require</span>(<span class="string">&#x27;../../Base/server/EntityFunction&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> fs = <span class="built_in">require</span>(<span class="string">&#x27;fs&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">initBucket</span> = <span class="keyword">async</span> minioClient =&gt; &#123;</span><br><span class="line">  <span class="keyword">let</span> exists</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">      exists = <span class="keyword">await</span> minioClient.<span class="title function_">bucketExists</span>(config.<span class="property">minio</span>.<span class="property">BUCKET</span>)</span><br><span class="line">  &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">      <span class="keyword">const</span> errMsg = <span class="string">`initBucket - bucketExists: <span class="subst">$&#123;err&#125;</span>`</span></span><br><span class="line">      <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(errMsg)</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (!exists) &#123;</span><br><span class="line">      <span class="keyword">try</span> &#123;</span><br><span class="line">          <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;Bucket creatd&#x27;</span>)</span><br><span class="line">          <span class="keyword">await</span> minioClient.<span class="title function_">makeBucket</span>(</span><br><span class="line">              config.<span class="property">minio</span>.<span class="property">BUCKET</span>,</span><br><span class="line">              process.<span class="property">env</span>.<span class="property">MINIO_REGION</span> || <span class="string">&#x27;eu-west-2&#x27;</span></span><br><span class="line">          )</span><br><span class="line">      &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">          <span class="keyword">const</span> errMsg = <span class="string">`initBucket - makeBucket: <span class="subst">$&#123;err&#125;</span>`</span></span><br><span class="line">          <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(errMsg)</span><br><span class="line">      &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">getInstance</span> = <span class="keyword">async</span>(<span class="params"></span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">let</span> minioClient;</span><br><span class="line">    <span class="keyword">await</span> <span class="title function_">getSqlData</span>()</span><br><span class="line">    minioClient = <span class="keyword">new</span> <span class="title class_">Minio</span>.<span class="title class_">Client</span>(config.<span class="property">minio</span>)</span><br><span class="line">    <span class="keyword">await</span> <span class="title function_">initBucket</span>(minioClient)</span><br><span class="line">    <span class="keyword">return</span> minioClient</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">formatDate</span>(<span class="params">fmt, date</span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> ret;</span><br><span class="line">    date = date || <span class="keyword">new</span> <span class="title class_">Date</span>()</span><br><span class="line">    <span class="keyword">const</span> opt = &#123;</span><br><span class="line">        <span class="string">&quot;Y+&quot;</span>: date.<span class="title function_">getFullYear</span>().<span class="title function_">toString</span>(), <span class="comment">// 年</span></span><br><span class="line">        <span class="string">&quot;m+&quot;</span>: (date.<span class="title function_">getMonth</span>() + <span class="number">1</span>).<span class="title function_">toString</span>(), <span class="comment">// 月</span></span><br><span class="line">        <span class="string">&quot;d+&quot;</span>: date.<span class="title function_">getDate</span>().<span class="title function_">toString</span>(), <span class="comment">// 日</span></span><br><span class="line">        <span class="string">&quot;H+&quot;</span>: date.<span class="title function_">getHours</span>().<span class="title function_">toString</span>(), <span class="comment">// 时</span></span><br><span class="line">        <span class="string">&quot;M+&quot;</span>: date.<span class="title function_">getMinutes</span>().<span class="title function_">toString</span>(), <span class="comment">// 分</span></span><br><span class="line">        <span class="string">&quot;S+&quot;</span>: date.<span class="title function_">getSeconds</span>().<span class="title function_">toString</span>() <span class="comment">// 秒</span></span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> k <span class="keyword">in</span> opt) &#123;</span><br><span class="line">        ret = <span class="keyword">new</span> <span class="title class_">RegExp</span>(<span class="string">&quot;(&quot;</span> + k + <span class="string">&quot;)&quot;</span>).<span class="title function_">exec</span>(fmt);</span><br><span class="line">        <span class="keyword">if</span> (ret) &#123;</span><br><span class="line">          fmt = fmt.<span class="title function_">replace</span>(ret[<span class="number">1</span>], (ret[<span class="number">1</span>].<span class="property">length</span> == <span class="number">1</span>) ? (opt[k]) : </span><br><span class="line">                (opt[k].<span class="title function_">padStart</span>(ret[<span class="number">1</span>].<span class="property">length</span>, <span class="string">&quot;0&quot;</span>)))</span><br><span class="line">        &#125;;</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">return</span> fmt;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">getSqlData</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> condition = &#123;</span><br><span class="line">      <span class="title class_">Classification</span>: <span class="string">&#x27;SystemManage&#x27;</span>,</span><br><span class="line">      <span class="title class_">Code</span>: &#123;</span><br><span class="line">          <span class="attr">$in</span>: [<span class="string">&#x27;FileServerMgtUser&#x27;</span>,<span class="string">&#x27;FileServerMgtPW&#x27;</span>, <span class="string">&#x27;FileServerURL&#x27;</span>]</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">let</span> parameters = <span class="keyword">await</span> entityFun.<span class="title function_">find</span>(<span class="string">&#x27;Parameter&#x27;</span>, condition);</span><br><span class="line">    <span class="keyword">if</span> (parameters &amp;&amp; parameters.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>, len = parameters.<span class="property">length</span>; i &lt; len; i++) &#123;</span><br><span class="line">            <span class="keyword">let</span> param = parameters[i];</span><br><span class="line">            <span class="keyword">if</span> (param.<span class="property">Code</span> == <span class="string">&#x27;FileServerMgtUser&#x27;</span>) &#123;</span><br><span class="line">                config.<span class="property">minio</span>.<span class="property">accessKey</span> = param.<span class="property">Value</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (param.<span class="property">Code</span> == <span class="string">&#x27;FileServerMgtPW&#x27;</span>) &#123;</span><br><span class="line">                config.<span class="property">minio</span>.<span class="property">secretKey</span> = param.<span class="property">Value</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (param.<span class="property">Code</span> == <span class="string">&#x27;FileServerURL&#x27;</span>) &#123;</span><br><span class="line">                <span class="keyword">let</span> url = param.<span class="property">Value</span>;</span><br><span class="line">                <span class="keyword">let</span> str = url.<span class="title function_">split</span>(<span class="string">&#x27;/&#x27;</span>)[<span class="number">0</span>];</span><br><span class="line">                config.<span class="property">minio</span>.<span class="property">endPoint</span> = str.<span class="title function_">split</span>(<span class="string">&#x27;:&#x27;</span>)[<span class="number">0</span>];</span><br><span class="line">                config.<span class="property">minio</span>.<span class="property">port</span> = <span class="title class_">Number</span>(str.<span class="title function_">split</span>(<span class="string">&#x27;:&#x27;</span>)[<span class="number">1</span>]);</span><br><span class="line">                config.<span class="property">minio</span>.<span class="property">BUCKET</span> = url.<span class="title function_">split</span>(<span class="string">&#x27;/&#x27;</span>)[<span class="number">1</span>];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  getInstance,</span><br><span class="line"></span><br><span class="line">  <span class="keyword">async</span> <span class="title function_">uploadFileSteam</span>(<span class="params">filename, file, fileType</span>) &#123;</span><br><span class="line">    <span class="keyword">var</span> fileStream = fs.<span class="title function_">createReadStream</span>(file)</span><br><span class="line">    <span class="keyword">const</span> filePath = <span class="title function_">formatDate</span>(<span class="string">&quot;YYYYmmdd&quot;</span>) + <span class="string">&quot;/&quot;</span> + filename;</span><br><span class="line">    <span class="keyword">const</span> minioClient = <span class="keyword">await</span> <span class="title function_">getInstance</span>()</span><br><span class="line">    fs.<span class="title function_">stat</span>(file, <span class="keyword">function</span>(<span class="params">err, stats</span>) &#123;</span><br><span class="line">      <span class="keyword">if</span> (err) &#123; <span class="keyword">return</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(err) &#125;</span><br><span class="line">      <span class="keyword">return</span> minioClient.<span class="title function_">putObject</span>(config.<span class="property">minio</span>.<span class="property">BUCKET</span>, filePath, </span><br><span class="line">            fileStream, stats.<span class="property">size</span>, &#123; <span class="string">&#x27;content-type&#x27;</span>: fileType &#125;)</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="keyword">async</span> <span class="title function_">uploadBase64</span>(<span class="params">filename, baseData, fileType,filePath</span>) &#123;</span><br><span class="line">    <span class="keyword">var</span> dataBuffer = <span class="keyword">new</span> <span class="title class_">Buffer</span>(baseData, <span class="string">&#x27;base64&#x27;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> minioClient = <span class="keyword">await</span> <span class="title function_">getInstance</span>()</span><br><span class="line">    <span class="keyword">if</span> (filePath &amp;&amp; filePath[filePath.<span class="property">length</span>-<span class="number">1</span>] != <span class="string">&#x27;/&#x27;</span>) &#123;</span><br><span class="line">        filePath = filePath+<span class="string">&#x27;/&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      <span class="keyword">await</span> minioClient.<span class="title function_">putObject</span>(config.<span class="property">minio</span>.<span class="property">BUCKET</span>, </span><br><span class="line">        filePath+filename, dataBuffer, &#123; <span class="string">&#x27;content-type&#x27;</span>: fileType &#125;)</span><br><span class="line">      <span class="keyword">let</span> obj = &#123;</span><br><span class="line">        <span class="attr">endPoint</span>: config.<span class="property">minio</span>.<span class="property">endPoint</span>,</span><br><span class="line">        <span class="attr">port</span>: config.<span class="property">minio</span>.<span class="property">port</span>,</span><br><span class="line">        <span class="attr">filePath</span>: filePath+filename,</span><br><span class="line">        <span class="attr">filename</span>: filename,</span><br><span class="line">        <span class="attr">bucket</span>: config.<span class="property">minio</span>.<span class="property">BUCKET</span>,</span><br><span class="line">        <span class="attr">bucketUrl</span>: <span class="string">&#x27;http://&#x27;</span> + config.<span class="property">minio</span>.<span class="property">endPoint</span> + <span class="string">&#x27;:&#x27;</span> + </span><br><span class="line">                config.<span class="property">minio</span>.<span class="property">port</span> + <span class="string">&#x27;/&#x27;</span> + config.<span class="property">minio</span>.<span class="property">BUCKET</span>,</span><br><span class="line">        <span class="attr">dataUrl</span>: <span class="string">&#x27;http://&#x27;</span> + config.<span class="property">minio</span>.<span class="property">endPoint</span> + <span class="string">&#x27;:&#x27;</span> + config.<span class="property">minio</span></span><br><span class="line">        .<span class="property">port</span> + <span class="string">&#x27;/&#x27;</span> + config.<span class="property">minio</span>.<span class="property">BUCKET</span> + <span class="string">&#x27;/&#x27;</span> +filePath+ filename</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">if</span> (filePath) &#123;</span><br><span class="line">          obj.<span class="property">bucketUrl</span> += <span class="string">&#x27;/&#x27;</span>;</span><br><span class="line">          obj.<span class="property">bucketUrl</span> += filePath;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> obj;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">      <span class="keyword">throw</span> err</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="keyword">async</span> <span class="title function_">listFiles</span>(<span class="params">prefix, endPoint, port, bucket</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="keyword">async</span> <span class="keyword">function</span>(<span class="params">resolve, reject</span>) &#123;</span><br><span class="line">      <span class="keyword">if</span> (!prefix) prefix = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">      <span class="keyword">await</span> <span class="title function_">getSqlData</span>()</span><br><span class="line">      <span class="keyword">let</span> minioObj = &#123;</span><br><span class="line">          <span class="attr">endPoint</span>: endPoint,</span><br><span class="line">          <span class="attr">port</span>: port,</span><br><span class="line">          <span class="attr">useSSL</span>: <span class="literal">false</span>,</span><br><span class="line">          <span class="attr">accessKey</span>: config.<span class="property">minio</span>.<span class="property">accessKey</span>,</span><br><span class="line">          <span class="attr">secretKey</span>: config.<span class="property">minio</span>.<span class="property">secretKey</span>,</span><br><span class="line">          <span class="attr">BUCKET</span>: bucket</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">let</span> newClient = <span class="keyword">new</span> <span class="title class_">Minio</span>.<span class="title class_">Client</span>(minioObj)</span><br><span class="line"></span><br><span class="line">      <span class="keyword">const</span> stream = newClient.<span class="title function_">listObjects</span>(bucket, prefix, <span class="literal">true</span>);</span><br><span class="line">      <span class="keyword">let</span> list = [];</span><br><span class="line">      stream.<span class="title function_">on</span>(<span class="string">&#x27;data&#x27;</span>, <span class="function"><span class="params">obj</span> =&gt;</span> &#123;</span><br><span class="line">          list.<span class="title function_">push</span>(obj);</span><br><span class="line">      &#125;)</span><br><span class="line">      stream.<span class="title function_">on</span>(<span class="string">&#x27;error&#x27;</span>, <span class="function"><span class="params">err</span> =&gt;</span> &#123;</span><br><span class="line">          <span class="title function_">reject</span>(err);</span><br><span class="line">      &#125;)</span><br><span class="line">      stream.<span class="title function_">on</span>(<span class="string">&#x27;end&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (list.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">          list.<span class="title function_">forEach</span>(<span class="function"><span class="params">item</span> =&gt;</span> &#123;</span><br><span class="line">              item.<span class="property">dataurl</span> = newClient.<span class="property">protocol</span> + <span class="string">&#x27;//&#x27;</span> + newClient.<span class="property">host</span> </span><br><span class="line">                + <span class="string">&#x27;:&#x27;</span> + newClient.<span class="property">port</span> + <span class="string">&#x27;/&#x27;</span> + bucket + <span class="string">&#x27;/&#x27;</span> + item.<span class="property">name</span></span><br><span class="line">          &#125;);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="title function_">resolve</span>(list);</span><br><span class="line">      &#125;)</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;,</span><br><span class="line"></span><br><span class="line">  <span class="keyword">async</span> <span class="title function_">getFile</span>(<span class="params">objName, tmpFile</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> minioClient = <span class="keyword">await</span> <span class="title function_">getInstance</span>()</span><br><span class="line">    <span class="keyword">return</span> minioClient.<span class="title function_">fGetObject</span>(config.<span class="property">minio</span>.<span class="property">BUCKET</span>, objName, tmpFile)</span><br><span class="line">  &#125;,</span><br><span class="line"></span><br><span class="line">  <span class="keyword">async</span> <span class="title function_">getFileStream</span>(<span class="params">objName</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> minioClient = <span class="keyword">await</span> <span class="title function_">getInstance</span>()</span><br><span class="line">    <span class="keyword">return</span> minioClient.<span class="title function_">getObject</span>(config.<span class="property">minio</span>.<span class="property">BUCKET</span>, objName)</span><br><span class="line">  &#125;,</span><br><span class="line"></span><br><span class="line">  <span class="keyword">async</span> <span class="title function_">deleteFile</span>(<span class="params">objName, endPoint, port, bucket</span>) &#123;</span><br><span class="line">      <span class="keyword">await</span> <span class="title function_">getSqlData</span>()</span><br><span class="line">      <span class="keyword">let</span> minioObj = &#123;</span><br><span class="line">          <span class="attr">endPoint</span>: endPoint,</span><br><span class="line">          <span class="attr">port</span>: port,</span><br><span class="line">          <span class="attr">useSSL</span>: <span class="literal">false</span>,</span><br><span class="line">          <span class="attr">accessKey</span>: config.<span class="property">minio</span>.<span class="property">accessKey</span>,</span><br><span class="line">          <span class="attr">secretKey</span>: config.<span class="property">minio</span>.<span class="property">secretKey</span>,</span><br><span class="line">          <span class="attr">BUCKET</span>: bucket</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">try</span> &#123;</span><br><span class="line">          <span class="keyword">let</span> newMinioClient = <span class="keyword">new</span> <span class="title class_">Minio</span>.<span class="title class_">Client</span>(minioObj)</span><br><span class="line">          <span class="keyword">await</span> newMinioClient.<span class="title function_">removeObject</span>(bucket, objName)</span><br><span class="line">          <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line">      &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">          <span class="keyword">return</span> err</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// config.js</span></span><br><span class="line"><span class="attr">minio</span>: &#123;</span><br><span class="line">    <span class="attr">endPoint</span>: <span class="string">&quot;172.20.45.333&quot;</span>,</span><br><span class="line">    <span class="attr">port</span>: <span class="number">9000</span>,</span><br><span class="line">    <span class="attr">useSSL</span>: <span class="literal">false</span>,</span><br><span class="line">    <span class="attr">accessKey</span>: <span class="string">&#x27;minioadmin&#x27;</span>,</span><br><span class="line">    <span class="attr">secretKey</span>: <span class="string">&#x27;minioadmin&#x27;</span>,</span><br><span class="line">    <span class="attr">BUCKET</span>: <span class="string">&#x27;bucket&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="JS-后台封装"><a href="#JS-后台封装" class="headerlink" title="JS 后台封装"></a>JS 后台封装</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// MinioClient.js</span></span><br><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"><span class="keyword">var</span> path = <span class="built_in">require</span>(<span class="string">&#x27;path&#x27;</span>);</span><br><span class="line"><span class="keyword">var</span> minio = <span class="built_in">require</span>(<span class="string">&#x27;../../../Utils/server/controllers/minio&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">handleError</span>(<span class="params">res, err</span>) &#123;</span><br><span class="line">    res.<span class="title function_">json</span>(&#123; <span class="title class_">Data</span>: <span class="literal">null</span>, <span class="title class_">Error</span>: err &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">handleSuccess</span>(<span class="params">res, data</span>) &#123;</span><br><span class="line">    res.<span class="title function_">json</span>(&#123; <span class="title class_">Data</span>: data, <span class="title class_">Error</span>: <span class="literal">null</span> &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 判断桶是否存在</span></span><br><span class="line"><span class="built_in">exports</span>.<span class="property">bucketExists</span> = <span class="keyword">function</span> (<span class="params">req, res</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (!req.<span class="property">body</span>.<span class="property">bucketName</span>) <span class="keyword">return</span> res.<span class="title function_">status</span>(<span class="number">400</span>).<span class="title function_">end</span>();</span><br><span class="line">    minio.<span class="title function_">bucketExists</span>(req.<span class="property">body</span>.<span class="property">bucketName</span>, <span class="keyword">function</span> (<span class="params">err, result</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (err) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="title function_">handleError</span>(res, err)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">handleSuccess</span>(res, &#123; <span class="attr">message</span>: <span class="string">&quot;bucket exist&quot;</span> &#125;);</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 删除桶</span></span><br><span class="line"><span class="built_in">exports</span>.<span class="property">removeBucket</span> = <span class="keyword">function</span> (<span class="params">req, res</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (!req.<span class="property">body</span>.<span class="property">bucketName</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">handleError</span>(res, &#123; <span class="attr">message</span>: <span class="string">&quot;桶名称为空&quot;</span> &#125;);</span><br><span class="line">    &#125; </span><br><span class="line">    minio.<span class="title function_">removeBucket</span>(req.<span class="property">body</span>.<span class="property">bucketName</span>, <span class="keyword">function</span> (<span class="params">err, result</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (err) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="title function_">handleError</span>(res, err)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">handleSuccess</span>(res, &#123; <span class="attr">message</span>: <span class="string">&quot;removed successfully&quot;</span> &#125;);</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 列出存储桶中所有对象</span></span><br><span class="line"><span class="built_in">exports</span>.<span class="property">listObjects</span> = <span class="keyword">async</span> (req, res) =&gt; &#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">let</span> objects = <span class="keyword">await</span> minio.<span class="title function_">listFiles</span>();</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">handleSuccess</span>(res, objects);</span><br><span class="line">    &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">handleError</span>(res, err);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">exports</span>.<span class="property">uploadFileSteam</span> = <span class="keyword">async</span> (req, res) =&gt; &#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">let</span> fPath = req.<span class="property">body</span>.<span class="property">filePath</span></span><br><span class="line">        <span class="keyword">let</span> fName = req.<span class="property">body</span>.<span class="property">filename</span> || <span class="string">&#x27;123.png&#x27;</span></span><br><span class="line">        <span class="keyword">let</span> fType = req.<span class="property">body</span>.<span class="property">fileType</span> || <span class="string">&#x27;image/png&#x27;</span></span><br><span class="line">        <span class="keyword">let</span> objs = <span class="keyword">await</span> minio.<span class="title function_">uploadFileSteam</span>(fName, fPath, fType);</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">handleSuccess</span>(res, objs);</span><br><span class="line">    &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">handleError</span>(res, err);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">exports</span>.<span class="property">uploadBase64</span> = <span class="keyword">async</span> (req, res) =&gt; &#123;</span><br><span class="line">    <span class="keyword">if</span> (!req.<span class="property">body</span>.<span class="property">filename</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">handleError</span>(res, &#123; <span class="attr">message</span>: <span class="string">&quot;请传入文件名&quot;</span> &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">var</span> dataurl = req.<span class="property">body</span>.<span class="property">dataurl</span></span><br><span class="line">    <span class="keyword">var</span> filename = req.<span class="property">body</span>.<span class="property">filename</span></span><br><span class="line">    <span class="keyword">var</span> arr = dataurl.<span class="title function_">split</span>(<span class="string">&#x27;,&#x27;</span>)</span><br><span class="line">    <span class="keyword">var</span> fType = arr[<span class="number">0</span>].<span class="title function_">match</span>(<span class="regexp">/:(.*?);/</span>)[<span class="number">1</span>] || <span class="string">&#x27;image/png&#x27;</span></span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">let</span> objects = <span class="keyword">await</span> minio.<span class="title function_">uploadBase64</span>(filename, arr[<span class="number">1</span>], fType)</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">handleSuccess</span>(res, objects)</span><br><span class="line">    &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">handleError</span>(res, err)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">exports</span>.<span class="property">deleteFile</span> = <span class="keyword">async</span> (req, res) =&gt; &#123;</span><br><span class="line">    <span class="keyword">if</span> (!req.<span class="property">body</span>.<span class="property">url</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">handleError</span>(res, &#123; <span class="attr">message</span>: <span class="string">&quot;请传入文件路径&quot;</span> &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">let</span> str = req.<span class="property">body</span>.<span class="property">url</span>.<span class="title function_">split</span>(<span class="string">&#x27;//&#x27;</span>)[<span class="number">1</span>];</span><br><span class="line">    <span class="keyword">let</span> arr = str.<span class="title function_">split</span>(<span class="string">&#x27;/&#x27;</span>);</span><br><span class="line">    <span class="keyword">let</span> point = arr[<span class="number">0</span>].<span class="title function_">split</span>(<span class="string">&quot;:&quot;</span>)[<span class="number">0</span>];</span><br><span class="line">    <span class="keyword">let</span> port = <span class="title class_">Number</span>(arr[<span class="number">0</span>].<span class="title function_">split</span>(<span class="string">&quot;:&quot;</span>)[<span class="number">1</span>]);</span><br><span class="line">    <span class="keyword">let</span> bucket = arr[<span class="number">1</span>];</span><br><span class="line">    <span class="keyword">let</span> fName = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i=<span class="number">0</span>; i&lt;arr.<span class="property">length</span>; i++) &#123;</span><br><span class="line">        <span class="keyword">if</span> (i &gt; <span class="number">1</span>) &#123;</span><br><span class="line">            fName += (arr[i] + <span class="string">&#x27;/&#x27;</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (i == (arr.<span class="property">length</span>-<span class="number">1</span>)) &#123;</span><br><span class="line">            fName += arr[i];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">let</span> objs = <span class="keyword">await</span> minio.<span class="title function_">deleteFile</span>(fName, point, port, bucket)</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">handleSuccess</span>(res, objs)</span><br><span class="line">    &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">handleError</span>(res, err)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 一次上传多张图片</span></span><br><span class="line"><span class="built_in">exports</span>.<span class="property">uploadImgs</span> = <span class="keyword">async</span> (req, res) =&gt; &#123;</span><br><span class="line">    <span class="keyword">let</span> newError;</span><br><span class="line">    <span class="keyword">let</span> imgs = req.<span class="property">body</span>.<span class="property">imgs</span>;</span><br><span class="line">    <span class="keyword">if</span> (!imgs) &#123;</span><br><span class="line">        newError = <span class="string">&#x27;imgs 字段缺失&#x27;</span></span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (!<span class="title class_">Array</span>.<span class="title function_">isArray</span>(imgs)) &#123;</span><br><span class="line">        newError = <span class="string">&#x27;imgs 数据格式错误&#x27;</span></span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (imgs.<span class="property">length</span> == <span class="number">0</span>) &#123;</span><br><span class="line">        newError = <span class="string">&#x27;请上传图片&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (newError) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">handleError</span>(res, &#123; <span class="attr">message</span>: newError &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">let</span> promise = [];</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i=<span class="number">0</span>; i&lt;imgs.<span class="property">length</span>; i++) &#123;</span><br><span class="line">        <span class="keyword">let</span> imgObj = imgs[i];</span><br><span class="line">        <span class="keyword">if</span> (imgObj.<span class="property">dataurl</span>.<span class="title function_">indexOf</span>(<span class="string">&#x27;,&#x27;</span>) == -<span class="number">1</span>) &#123;</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">let</span> filename = imgObj.<span class="property">filename</span>;</span><br><span class="line">        <span class="keyword">let</span> filePath = imgObj.<span class="property">filePath</span> || <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">        <span class="keyword">let</span> arr = imgObj.<span class="property">dataurl</span>.<span class="title function_">split</span>(<span class="string">&#x27;,&#x27;</span>);</span><br><span class="line">        <span class="keyword">let</span> fileType = arr[<span class="number">0</span>].<span class="title function_">match</span>(<span class="regexp">/:(.*?);/</span>)[<span class="number">1</span>] || <span class="string">&#x27;image/png&#x27;</span>;</span><br><span class="line">        promise.<span class="title function_">push</span>(<span class="keyword">await</span> minio.<span class="title function_">uploadBase64</span>(filename, arr[<span class="number">1</span>], </span><br><span class="line">        fileType, filePath))</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title class_">Promise</span>.<span class="title function_">all</span>(promise).<span class="title function_">then</span>(<span class="function"><span class="params">result</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">handleSuccess</span>(res, result)</span><br><span class="line">    &#125;).<span class="property">catch</span> (<span class="function"><span class="params">err</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">handleError</span>(res, &#123; <span class="attr">message</span>: err.<span class="property">message</span> &#125;)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">exports</span>.<span class="property">downloadImgsFunc</span> = <span class="keyword">async</span> (req, res) =&gt; &#123;</span><br><span class="line">    <span class="keyword">if</span> (!req.<span class="property">body</span>.<span class="property">folderName</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">handleError</span>(res, &#123; <span class="attr">message</span>: <span class="string">&quot;请传入要下载的图片路径&quot;</span> &#125;)</span><br><span class="line">    &#125; </span><br><span class="line">    <span class="keyword">let</span> url = req.<span class="property">body</span>.<span class="property">folderName</span>;</span><br><span class="line">    <span class="keyword">if</span> (url.<span class="title function_">charAt</span>(url.<span class="property">length</span>-<span class="number">1</span>) != <span class="string">&#x27;/&#x27;</span>) &#123;</span><br><span class="line">        url += <span class="string">&#x27;/&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">let</span> str = url.<span class="title function_">split</span>(<span class="string">&#x27;//&#x27;</span>)[<span class="number">1</span>];</span><br><span class="line">    <span class="keyword">let</span> arr = str.<span class="title function_">split</span>(<span class="string">&#x27;/&#x27;</span>);</span><br><span class="line">    <span class="keyword">let</span> point = arr[<span class="number">0</span>].<span class="title function_">split</span>(<span class="string">&quot;:&quot;</span>)[<span class="number">0</span>];</span><br><span class="line">    <span class="keyword">let</span> port = <span class="title class_">Number</span>(arr[<span class="number">0</span>].<span class="title function_">split</span>(<span class="string">&quot;:&quot;</span>)[<span class="number">1</span>]);</span><br><span class="line">    <span class="keyword">let</span> bucket = arr[<span class="number">1</span>];</span><br><span class="line">    <span class="keyword">let</span> foldName = <span class="string">&quot;&quot;</span>;</span><br><span class="line">    <span class="keyword">let</span> foldArr = arr.<span class="title function_">slice</span>(<span class="number">2</span>, arr.<span class="property">length</span>-<span class="number">1</span>);</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i=<span class="number">0</span>; i &lt; foldArr.<span class="property">length</span>; i++) &#123;</span><br><span class="line">        foldName += (foldArr[i] + <span class="string">&#x27;/&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    foldName = foldName.<span class="title function_">substring</span>(<span class="number">0</span>, foldName.<span class="property">length</span>-<span class="number">1</span>)</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// 列出存储桶所有对象</span></span><br><span class="line">        <span class="keyword">let</span> objs = <span class="keyword">await</span> minio.<span class="title function_">listFiles</span>(foldName, point, port, bucket)   </span><br><span class="line">        <span class="keyword">return</span> objs</span><br><span class="line">    &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="JS-前台调用"><a href="#JS-前台调用" class="headerlink" title="JS 前台调用"></a>JS 前台调用</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="title class_">Http</span>.<span class="title function_">post</span>(&#123;</span><br><span class="line">    <span class="attr">url</span>: <span class="string">&quot;/api/minio/downloadImgs&quot;</span>,</span><br><span class="line">    <span class="attr">data</span>: &#123; <span class="attr">foldName</span>: <span class="string">&#x27;http://172.20.45.137:9000/bucket/chuang&#x27;</span> &#125;</span><br><span class="line">&#125;).<span class="title function_">then</span>(<span class="keyword">function</span> (<span class="params">result</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(result)</span><br><span class="line">&#125;, <span class="keyword">function</span> (<span class="params">err</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">error</span>(err)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="title class_">Http</span>.<span class="title function_">post</span>(&#123;</span><br><span class="line">    <span class="attr">url</span>: <span class="string">&quot;/api/minio/uploadImgs&quot;</span>,</span><br><span class="line">    <span class="attr">data</span>: &#123; <span class="attr">imgs</span>: [baseImg] &#125;</span><br><span class="line">&#125;).<span class="title function_">then</span>(<span class="keyword">function</span> (<span class="params">result</span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> foldName = result[<span class="number">0</span>].<span class="property">bucketUrl</span> + <span class="string">&#x27;/chuang&#x27;</span></span><br><span class="line">&#125;).<span class="title function_">catch</span>(<span class="keyword">function</span> (<span class="params">err</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">error</span>(err)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<h1 id="六、补丁版本管理"><a href="#六、补丁版本管理" class="headerlink" title="六、补丁版本管理"></a>六、补丁版本管理</h1><h2 id="补丁下载"><a href="#补丁下载" class="headerlink" title="补丁下载"></a>补丁下载</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br></pre></td><td class="code"><pre><span class="line"> $scope.<span class="property">downloadFile</span> = <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">     <span class="keyword">let</span> record = $scope.<span class="property">Module</span>.<span class="property">SystemManager</span>.<span class="property">FocusedRecord</span>;</span><br><span class="line">     <span class="keyword">if</span> (<span class="title function_">toNum</span>(record.<span class="property">NewVersion</span>) == <span class="title function_">toNum</span>(record.<span class="property">Version</span> || <span class="string">&#x27;0.0.0&#x27;</span>)) &#123;</span><br><span class="line">         <span class="title class_">BaseFunction</span>.<span class="title function_">alert</span>(<span class="string">&#x27;该版本是最新补丁！&#x27;</span>, <span class="string">&#x27;补丁下载错误&#x27;</span>);</span><br><span class="line">     &#125;</span><br><span class="line">     <span class="comment">// 补丁备份</span></span><br><span class="line">     <span class="keyword">let</span> <span class="title class_">FilePaths</span> = [&#123;</span><br><span class="line">         <span class="title class_">OldPath</span>: <span class="string">&#x27;/downloads/umif-pc.zip&#x27;</span>,</span><br><span class="line">         <span class="title class_">NewPath</span>: <span class="string">&#x27;/downloads/umif-pc-back.zip&#x27;</span></span><br><span class="line">     &#125;];</span><br><span class="line">     <span class="keyword">let</span> appStoreUrl = <span class="string">&#x27;u9cmes.diwork.com&#x27;</span></span><br><span class="line">     <span class="keyword">let</span> ip = appStoreUrl.<span class="title function_">split</span>(<span class="string">&#x27;:&#x27;</span>)[<span class="number">0</span>];</span><br><span class="line">     <span class="keyword">let</span> prefix = <span class="title function_">verifyIp</span>(ip) ? <span class="string">&#x27;http://&#x27;</span> : <span class="string">&#x27;https://&#x27;</span>;</span><br><span class="line">     <span class="keyword">let</span> params = &#123;</span><br><span class="line">         <span class="title class_">ServerPath</span>: <span class="string">`<span class="subst">$&#123;prefix&#125;</span><span class="subst">$&#123;appStoreUrl&#125;</span>/api/App/getFileStream`</span>,</span><br><span class="line">         <span class="title class_">DownloadFileName</span>: <span class="string">&#x27;umif-pc.zip&#x27;</span>,  <span class="comment">// 文件全名</span></span><br><span class="line">         <span class="title class_">FileName</span>: <span class="literal">null</span>,                   <span class="comment">// 本地保存文件名，默认为源文件名称</span></span><br><span class="line">         <span class="title class_">DeleteFileName</span>: <span class="literal">null</span>,             <span class="comment">// 本地要删除的文件名，可空</span></span><br><span class="line">         <span class="title class_">SocketId</span>: <span class="literal">null</span>                    <span class="comment">// 通过 Socket 向前端通知过程</span></span><br><span class="line">     &#125;</span><br><span class="line">     <span class="title class_">BaseFunction</span>.<span class="title function_">request</span>(<span class="string">&#x27;/api/base/fileRenames&#x27;</span>, &#123;<span class="title class_">FilePaths</span>&#125;)</span><br><span class="line">     .<span class="title function_">then</span>(<span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">         <span class="keyword">return</span> <span class="title class_">BaseFunction</span>.<span class="title function_">request</span>(<span class="string">&#x27;/api/base/downloadFile&#x27;</span>, params)</span><br><span class="line">     &#125;)</span><br><span class="line">     .<span class="title function_">then</span>(<span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">         <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;下载成功&#x27;</span>);</span><br><span class="line">     &#125;)</span><br><span class="line">     .<span class="title function_">catch</span>(<span class="keyword">function</span> (<span class="params">err</span>) &#123;</span><br><span class="line">         <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">`<span class="subst">$&#123;fileName&#125;</span>下载失败：<span class="subst">$&#123;err.message&#125;</span>`</span>);</span><br><span class="line">     &#125;)</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 校验url是否是IP</span></span><br><span class="line"> <span class="keyword">function</span> <span class="title function_">verifyIp</span>(<span class="params">ip = <span class="string">&#x27;&#x27;</span></span>) &#123;</span><br><span class="line">     <span class="keyword">return</span> <span class="regexp">/^(([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])(\.(?!$)|(?=$)))&#123;4&#125;$/</span>.<span class="title function_">test</span>(ip);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">function</span> <span class="title function_">toNum</span>(<span class="params">a</span>) &#123;</span><br><span class="line">     <span class="keyword">var</span> a = a.<span class="title function_">toString</span>();</span><br><span class="line">     <span class="keyword">var</span> c = a.<span class="title function_">split</span>(<span class="string">&#x27;.&#x27;</span>);     <span class="comment">// a.split(/\./);</span></span><br><span class="line">     <span class="keyword">var</span> num_place = [<span class="string">&quot;&quot;</span>, <span class="string">&quot;0&quot;</span>, <span class="string">&quot;00&quot;</span>, <span class="string">&quot;000&quot;</span>, <span class="string">&quot;0000&quot;</span>],</span><br><span class="line">       r = num_place.<span class="title function_">reverse</span>();</span><br><span class="line">     <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; c.<span class="property">length</span>; i++) &#123;</span><br><span class="line">       <span class="keyword">var</span> len = c[i].<span class="property">length</span>;</span><br><span class="line">       c[i] = r[len] + c[i];</span><br><span class="line">     &#125;</span><br><span class="line">     <span class="keyword">return</span> c.<span class="title function_">join</span>(<span class="string">&#x27;&#x27;</span>);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 文件重命名</span></span><br><span class="line"> <span class="built_in">exports</span>.<span class="property">fileRenames</span> = <span class="keyword">function</span>(<span class="params">req, res</span>) &#123;</span><br><span class="line">     <span class="keyword">var</span> newErr = <span class="keyword">new</span> <span class="title class_">Error</span>();</span><br><span class="line">     newErr.<span class="property">leval</span> = <span class="number">5</span>;</span><br><span class="line">     newErr.<span class="property">title</span> = <span class="string">&#x27;文件重命名失败&#x27;</span>;</span><br><span class="line">     newErr.<span class="property">message</span> = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line"></span><br><span class="line">     <span class="keyword">var</span> excuteCount = <span class="number">0</span>;</span><br><span class="line">     <span class="keyword">var</span> parameter = req.<span class="property">body</span>;</span><br><span class="line">     <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; parameter.<span class="property">FilePaths</span>.<span class="property">length</span>; i++) &#123;</span><br><span class="line">         <span class="keyword">let</span> oldPath = process.<span class="title function_">cwd</span>() + parameter.<span class="property">FilePaths</span>[i].<span class="property">OldPath</span>;</span><br><span class="line">         <span class="keyword">let</span> newPath = process.<span class="title function_">cwd</span>() + parameter.<span class="property">FilePaths</span>[i].<span class="property">NewPath</span>;</span><br><span class="line">         <span class="title function_">fileRename</span>(oldPath, newPath, <span class="keyword">function</span>(<span class="params">err</span>) &#123;</span><br><span class="line">             <span class="keyword">if</span> (err) &#123;</span><br><span class="line">                 newErr.<span class="property">message</span> += (<span class="string">&quot;\r\n&quot;</span> + oldPath);</span><br><span class="line">             &#125;</span><br><span class="line">             excuteCount++;</span><br><span class="line">             <span class="keyword">if</span> (excuteCount == parameter.<span class="property">FilePaths</span>.<span class="property">length</span>) &#123;</span><br><span class="line">                 <span class="keyword">if</span> (newErr.<span class="property">message</span> != <span class="string">&quot;&quot;</span>) &#123;</span><br><span class="line">                   newErr.<span class="property">message</span> = <span class="string">&quot;失败文件：&quot;</span> + newErr.<span class="property">message</span>;</span><br><span class="line">                   res.<span class="title function_">json</span>(&#123; <span class="title class_">Error</span>: newErr &#125;);</span><br><span class="line">                 &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                   res.<span class="title function_">json</span>(&#123; <span class="title class_">Data</span>: excuteCount &#125;);</span><br><span class="line">                 &#125;</span><br><span class="line">             &#125;</span><br><span class="line">         &#125;);</span><br><span class="line">     &#125;</span><br><span class="line"> &#125;;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">function</span> <span class="title function_">fileRename</span>(<span class="params">oldPath, newPath, completeFun</span>) &#123;</span><br><span class="line">     fs.<span class="title function_">exists</span>(oldPath, <span class="keyword">function</span>(<span class="params">isExists</span>) &#123;</span><br><span class="line">         <span class="keyword">if</span> (isExists) &#123;</span><br><span class="line">             fs.<span class="title function_">rename</span>(oldPath, newPath, <span class="keyword">function</span>(<span class="params">err</span>) &#123;</span><br><span class="line">                 completeFun &amp;&amp; <span class="title function_">completeFun</span>(err);</span><br><span class="line">             &#125;);</span><br><span class="line">         &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">             <span class="keyword">var</span> newErr = <span class="keyword">new</span> <span class="title class_">Error</span>();</span><br><span class="line">             newErr.<span class="property">leval</span> = <span class="number">0</span>;</span><br><span class="line">             newErr.<span class="property">title</span> = <span class="string">&#x27;重命名失败&#x27;</span>;</span><br><span class="line">             newErr.<span class="property">message</span> = <span class="string">&#x27;文件不存在&#x27;</span>;</span><br><span class="line">             completeFun &amp;&amp; <span class="title function_">completeFun</span>(newErr);</span><br><span class="line">         &#125;</span><br><span class="line">     &#125;)</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 下载文件，从别的服务器下载文件</span></span><br><span class="line"> <span class="built_in">exports</span>.<span class="property">downloadFile</span> = <span class="keyword">function</span>(<span class="params">req, res</span>) &#123;</span><br><span class="line">     <span class="keyword">var</span> params = req.<span class="property">body</span>;</span><br><span class="line">     <span class="title function_">downloadFile</span>(params.<span class="property">ServerPath</span>, params.<span class="property">DownloadFileName</span>, </span><br><span class="line">     params.<span class="property">FileName</span>, params.<span class="property">DeleteFileName</span>, params.<span class="property">SocketId</span>, </span><br><span class="line">     <span class="keyword">function</span>(<span class="params">err, file</span>) &#123;</span><br><span class="line">         <span class="keyword">if</span> (!err) &#123;</span><br><span class="line">             res.<span class="title function_">json</span>(&#123; <span class="title class_">Data</span>: file &#125;);</span><br><span class="line">             <span class="keyword">return</span></span><br><span class="line">         &#125;</span><br><span class="line">         <span class="keyword">var</span> newErr = <span class="keyword">new</span> <span class="title class_">Error</span>();</span><br><span class="line">         newErr.<span class="property">leval</span> = <span class="number">5</span>;</span><br><span class="line">         newErr.<span class="property">title</span> = <span class="string">&#x27;下载失败&#x27;</span>;</span><br><span class="line">         newErr.<span class="property">message</span> = <span class="string">&#x27;未能连接上下载服务器&#x27;</span>;</span><br><span class="line">         <span class="title class_">BaseFun</span>.<span class="title function_">errorLog</span>(<span class="string">&#x27;补丁下载失败：&#x27;</span>, err.<span class="property">message</span>);</span><br><span class="line">         res.<span class="title function_">json</span>(&#123; <span class="title class_">Error</span>: newErr &#125;);</span><br><span class="line">     &#125;);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">function</span> <span class="title function_">downloadFile</span>(<span class="params">serverPath, downloadFileName, fileName, </span></span><br><span class="line"><span class="params"> deleteFileName, socketId, returnHandle</span>) &#123;</span><br><span class="line">     <span class="keyword">var</span> isHttps = serverPath.<span class="title function_">indexOf</span>(<span class="string">&#x27;https&#x27;</span>);</span><br><span class="line">     serverPath = serverPath.<span class="title function_">replace</span>(<span class="regexp">/\\/g</span>, <span class="string">&quot;/&quot;</span>);</span><br><span class="line">     fileName = fileName || downloadFileName;</span><br><span class="line">     <span class="keyword">if</span> (serverPath.<span class="title function_">indexOf</span>(<span class="string">&#x27;//&#x27;</span>) &gt; -<span class="number">1</span>) &#123;</span><br><span class="line">         serverPath = serverPath.<span class="title function_">split</span>(<span class="string">&#x27;//&#x27;</span>)[<span class="number">1</span>];   <span class="comment">// 去掉 http 头</span></span><br><span class="line">     &#125;</span><br><span class="line">     <span class="comment">// 文件服务器信息</span></span><br><span class="line">     <span class="keyword">var</span> serverAddress = serverPath.<span class="title function_">substring</span>(<span class="number">0</span>, serverPath.<span class="title function_">indexOf</span>(<span class="string">&#x27;/&#x27;</span>)); </span><br><span class="line">     <span class="keyword">var</span> serverApiPath = serverPath.<span class="title function_">substring</span>(serverPath.<span class="title function_">indexOf</span>(<span class="string">&#x27;/&#x27;</span>), </span><br><span class="line">     serverPath.<span class="property">length</span>);</span><br><span class="line">     <span class="keyword">var</span> serverHostName = serverAddress;</span><br><span class="line">     <span class="keyword">var</span> serverPort = <span class="number">80</span>;</span><br><span class="line">     <span class="keyword">if</span> (serverAddress.<span class="title function_">indexOf</span>(<span class="string">&#x27;:&#x27;</span>) &gt; <span class="number">0</span>) &#123;</span><br><span class="line">         serverHostName = serverAddress.<span class="title function_">split</span>(<span class="string">&#x27;:&#x27;</span>)[<span class="number">0</span>];</span><br><span class="line">         serverPort = <span class="built_in">parseInt</span>(serverAddress.<span class="title function_">split</span>(<span class="string">&#x27;:&#x27;</span>)[<span class="number">1</span>]);</span><br><span class="line">     &#125;</span><br><span class="line">     <span class="keyword">var</span> <span class="title class_">FilePath</span> = config.<span class="property">System</span>.<span class="property">FilePath</span> || <span class="string">&#x27;./downloads/&#x27;</span></span><br><span class="line">     <span class="keyword">var</span> fileFullPath = <span class="title class_">FilePath</span> + fileName;</span><br><span class="line">     <span class="keyword">var</span> fileWriteStream = fs.<span class="title function_">createWriteStream</span>(fileFullPath + <span class="string">&#x27;.temp&#x27;</span>);</span><br><span class="line"></span><br><span class="line">     <span class="keyword">var</span> parameter = <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123; <span class="title class_">FileName</span>: fileName &#125;);</span><br><span class="line">     <span class="keyword">if</span> (isHttps &gt; -<span class="number">1</span>) &#123;</span><br><span class="line">       <span class="keyword">var</span> options = &#123;</span><br><span class="line">           <span class="string">&#x27;method&#x27;</span>: <span class="string">&#x27;POST&#x27;</span>,</span><br><span class="line">           <span class="string">&#x27;hostname&#x27;</span>: serverHostName,</span><br><span class="line">           <span class="string">&#x27;path&#x27;</span>: serverApiPath,</span><br><span class="line">           <span class="string">&#x27;maxRedirects&#x27;</span>: <span class="number">20</span>,</span><br><span class="line">           <span class="string">&#x27;headers&#x27;</span>: &#123;</span><br><span class="line">             <span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&#x27;application/json&#x27;</span>,</span><br><span class="line">             <span class="string">&#x27;Cookie&#x27;</span>: <span class="string">&#x27;acw_tc=2760827916413586286573778e6933772&#x27;</span></span><br><span class="line">           &#125;</span><br><span class="line">       &#125;;</span><br><span class="line">       <span class="comment">// let https = require(&#x27;https&#x27;);</span></span><br><span class="line">       <span class="keyword">var</span> req = https.<span class="title function_">request</span>(options, <span class="keyword">function</span>(<span class="params">res</span>) &#123;</span><br><span class="line">           <span class="keyword">var</span> eventName;</span><br><span class="line"></span><br><span class="line">           res.<span class="title function_">on</span>(<span class="string">&quot;data&quot;</span>, <span class="keyword">function</span>(<span class="params">data</span>) &#123;</span><br><span class="line">               fileWriteStream.<span class="title function_">write</span>(data);</span><br><span class="line">               <span class="keyword">if</span> (!socketId) &#123; <span class="keyword">return</span> &#125;</span><br><span class="line">               eventName = downloadFileName + <span class="string">&quot;_DownloadSize&quot;</span></span><br><span class="line">               socket.<span class="title function_">emitBySocketId</span>(socketId, eventName, data.<span class="property">length</span>);</span><br><span class="line">           &#125;);</span><br><span class="line"></span><br><span class="line">           res.<span class="title function_">on</span>(<span class="string">&quot;end&quot;</span>, <span class="keyword">function</span>(<span class="params">data</span>) &#123;</span><br><span class="line">               fileWriteStream.<span class="title function_">end</span>();</span><br><span class="line">               <span class="keyword">if</span> (deleteFileName) &#123;</span><br><span class="line">                   fs.<span class="title function_">unlinkSync</span>(<span class="title class_">FilePath</span> + deleteFileName); <span class="comment">// 删除已有文件</span></span><br><span class="line">               &#125;</span><br><span class="line">               fs.<span class="title function_">renameSync</span>(fileFullPath + <span class="string">&#x27;.temp&#x27;</span>, fileFullPath);</span><br><span class="line">               <span class="keyword">if</span> (socketId) &#123;</span><br><span class="line">                   eventName = downloadFileName + <span class="string">&quot;_DownloadComplete&quot;</span></span><br><span class="line">                   socket.<span class="title function_">emitBySocketId</span>(socketId, eventName, <span class="literal">true</span>);</span><br><span class="line">               &#125;</span><br><span class="line">               <span class="title function_">returnHandle</span>(<span class="literal">null</span>, &#123; <span class="title class_">FileName</span>: fileName &#125;);</span><br><span class="line">           &#125;);</span><br><span class="line"></span><br><span class="line">           res.<span class="title function_">on</span>(<span class="string">&quot;error&quot;</span>, <span class="keyword">function</span>(<span class="params">error</span>) &#123;</span><br><span class="line">               <span class="variable language_">console</span>.<span class="title function_">error</span>(error);</span><br><span class="line">           &#125;);</span><br><span class="line">         &#125;);</span><br><span class="line">         req.<span class="title function_">write</span>(parameter);</span><br><span class="line">         req.<span class="title function_">on</span>(<span class="string">&#x27;error&#x27;</span>, <span class="keyword">function</span>(<span class="params">err</span>) &#123;</span><br><span class="line">             <span class="title function_">returnHandle</span>(err);</span><br><span class="line">         &#125;);</span><br><span class="line">         req.<span class="title function_">end</span>();</span><br><span class="line">     &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">         <span class="keyword">var</span> options = &#123;</span><br><span class="line">             <span class="attr">hostname</span>: serverHostName,</span><br><span class="line">             <span class="attr">port</span>: serverPort,</span><br><span class="line">             <span class="attr">path</span>: serverApiPath,</span><br><span class="line">             <span class="attr">method</span>: <span class="string">&#x27;POST&#x27;</span>,</span><br><span class="line">             <span class="attr">headers</span>: &#123;</span><br><span class="line">               <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&#x27;application/json&#x27;</span>,</span><br><span class="line">               <span class="string">&quot;Content-Length&quot;</span>: parameter.<span class="property">length</span>,</span><br><span class="line">             &#125;</span><br><span class="line">         &#125;;</span><br><span class="line">         <span class="keyword">var</span> fileFullPath = <span class="title class_">FilePath</span> + fileName;</span><br><span class="line">         <span class="keyword">var</span> fileWriteStream = fs.<span class="title function_">createWriteStream</span>(fileFullPath + <span class="string">&#x27;.temp&#x27;</span>);</span><br><span class="line">         <span class="keyword">var</span> httpRequest = http.<span class="title function_">request</span>(options, <span class="keyword">function</span>(<span class="params">httpResponse</span>) &#123;</span><br><span class="line">             httpResponse.<span class="title function_">on</span>(<span class="string">&#x27;data&#x27;</span>, <span class="keyword">function</span>(<span class="params">data</span>) &#123;</span><br><span class="line">                 fileWriteStream.<span class="title function_">write</span>(data);</span><br><span class="line">                 <span class="keyword">if</span> (!socketId) &#123; <span class="keyword">return</span> &#125;</span><br><span class="line">                 eventName = downloadFileName + <span class="string">&quot;_DownloadSize&quot;</span></span><br><span class="line">                 socket.<span class="title function_">emitBySocketId</span>(socketId, eventName, data.<span class="property">length</span>);</span><br><span class="line">             &#125;);</span><br><span class="line">             httpResponse.<span class="title function_">on</span>(<span class="string">&#x27;end&#x27;</span>, <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">                 fileWriteStream.<span class="title function_">end</span>();</span><br><span class="line">                 <span class="keyword">if</span> (deleteFileName) &#123;</span><br><span class="line">                     fs.<span class="title function_">unlinkSync</span>(<span class="title class_">FilePath</span> + deleteFileName);</span><br><span class="line">                 &#125;</span><br><span class="line">                 fs.<span class="title function_">renameSync</span>(fileFullPath + <span class="string">&#x27;.temp&#x27;</span>, fileFullPath);</span><br><span class="line">                 <span class="keyword">if</span> (socketId) &#123;</span><br><span class="line">                     eventName = downloadFileName + <span class="string">&quot;_DownloadComplete&quot;</span></span><br><span class="line">                     socket.<span class="title function_">emitBySocketId</span>(socketId, eventName, <span class="literal">true</span>);</span><br><span class="line">                 &#125;</span><br><span class="line">                 <span class="title function_">returnHandle</span>(<span class="literal">null</span>, &#123; <span class="title class_">FileName</span>: fileName &#125;);</span><br><span class="line">             &#125;);</span><br><span class="line">         &#125;);</span><br><span class="line">         httpRequest.<span class="title function_">write</span>(parameter);</span><br><span class="line">         httpRequest.<span class="title function_">on</span>(<span class="string">&#x27;error&#x27;</span>, <span class="keyword">function</span>(<span class="params">err</span>) &#123;</span><br><span class="line">             <span class="title function_">returnHandle</span>(err);</span><br><span class="line">         &#125;);</span><br><span class="line">         httpRequest.<span class="title function_">end</span>();</span><br><span class="line">       &#125;</span><br><span class="line"> &#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">// socket.js</span></span><br><span class="line"> <span class="keyword">var</span> <span class="title class_">BaseConst</span> = <span class="built_in">require</span>(<span class="string">&#x27;./Const&#x27;</span>),</span><br><span class="line"><span class="title class_">BaseFun</span> = <span class="built_in">require</span>(<span class="string">&#x27;./Function&#x27;</span>),</span><br><span class="line">http = <span class="built_in">require</span>(<span class="string">&quot;http&quot;</span>),</span><br><span class="line">socketIo = <span class="built_in">require</span>(<span class="string">&#x27;socket.io&#x27;</span>)(http);</span><br><span class="line"> <span class="keyword">var</span> clientList = &#123;&#125;;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 发送给指定连接</span></span><br><span class="line"> <span class="built_in">exports</span>.<span class="property">emitBySocketId</span> = <span class="keyword">function</span>(<span class="params">socketId, eventName, data</span>)&#123;</span><br><span class="line">     <span class="keyword">if</span> (clientList.<span class="title function_">hasOwnProperty</span>(socketId)) &#123;</span><br><span class="line">         clientList[socketId].<span class="title function_">emit</span>(eventName, data);</span><br><span class="line">     &#125;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 广播给所有人</span></span><br><span class="line"> <span class="built_in">exports</span>.<span class="property">emit</span> = <span class="keyword">function</span>(<span class="params">eventName, data</span>)&#123;</span><br><span class="line">     socketIo.<span class="title function_">emit</span>(eventName, data);</span><br><span class="line"> &#125;;</span><br><span class="line"> <span class="comment">// 广播给该房间的所有人，包括自己</span></span><br><span class="line"> <span class="built_in">exports</span>.<span class="property">emitRoom</span> = <span class="keyword">function</span>(<span class="params">eventName, roomName, data</span>)&#123;</span><br><span class="line">     socketIo.<span class="title function_">in</span>(roomName).<span class="title function_">emit</span>(eventName, data);</span><br><span class="line"> &#125;;</span><br><span class="line"></span><br><span class="line"> <span class="built_in">exports</span>.<span class="property">create</span> = <span class="keyword">function</span>(<span class="params">socketPort</span>)&#123;</span><br><span class="line">     <span class="keyword">var</span> server = http.<span class="title function_">createServer</span>().<span class="title function_">listen</span>(socketPort);</span><br><span class="line">     socketIo.<span class="title function_">listen</span>(server);</span><br><span class="line"></span><br><span class="line">     socketIo.<span class="title function_">on</span>(<span class="string">&#x27;connection&#x27;</span>, <span class="keyword">function</span>(<span class="params">socket</span>) &#123;</span><br><span class="line"></span><br><span class="line">       <span class="keyword">if</span>(!clientList.<span class="title function_">hasOwnProperty</span>(socket.<span class="property">id</span>))&#123;</span><br><span class="line">           clientList[socket.<span class="property">id</span>] = socket;</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="comment">// 发给自己</span></span><br><span class="line">       socket.<span class="title function_">on</span>(<span class="string">&#x27;toSelf&#x27;</span>, <span class="keyword">function</span>(<span class="params">data</span>) &#123;</span><br><span class="line">           socket.<span class="title function_">emit</span>(data.<span class="property">EventName</span>, data.<span class="property">Data</span>);	</span><br><span class="line">       &#125;);</span><br><span class="line">       <span class="comment">// 发送除自己的其他所有人</span></span><br><span class="line">       socket.<span class="title function_">on</span>(<span class="string">&#x27;toOther&#x27;</span>, <span class="keyword">function</span>(<span class="params">data</span>) &#123;</span><br><span class="line">           socket.<span class="property">broadcast</span>.<span class="title function_">emit</span>(data.<span class="property">EventName</span>, data.<span class="property">Data</span>);		</span><br><span class="line">       &#125;);</span><br><span class="line">       <span class="comment">// 发给所有人，包括自己</span></span><br><span class="line">       socket.<span class="title function_">on</span>(<span class="string">&#x27;toAll&#x27;</span>, <span class="keyword">function</span>(<span class="params">data</span>) &#123;</span><br><span class="line">           socketIo.<span class="title function_">emit</span>(data.<span class="property">EventName</span>, data.<span class="property">Data</span>);	</span><br><span class="line">       &#125;);</span><br><span class="line"></span><br><span class="line">       socket.<span class="title function_">on</span>(<span class="string">&#x27;joinRoom&#x27;</span>, <span class="keyword">function</span>(<span class="params">data</span>) &#123;</span><br><span class="line">           socket.<span class="title function_">join</span>(data.<span class="property">RoomName</span>);</span><br><span class="line">       &#125;);</span><br><span class="line">       socket.<span class="title function_">on</span>(<span class="string">&#x27;leaveRoom&#x27;</span>, <span class="keyword">function</span>(<span class="params">data</span>) &#123;</span><br><span class="line">           socket.<span class="title function_">leave</span>(data.<span class="property">RoomName</span>);</span><br><span class="line">       &#125;);</span><br><span class="line">       <span class="comment">// 向一个房间广播消息（发送者收不到消息)</span></span><br><span class="line">       socket.<span class="title function_">on</span>(<span class="string">&#x27;toRoom&#x27;</span>, <span class="keyword">function</span>(<span class="params">data</span>) &#123;</span><br><span class="line">           socket.<span class="property">broadcast</span>.<span class="title function_">to</span>(data.<span class="property">RoomName</span>).<span class="title function_">emit</span>(data.<span class="property">EventName</span>, data.<span class="property">Data</span>);</span><br><span class="line">       &#125;);</span><br><span class="line">       <span class="comment">// 向一个房间广播消息（包括发送者都能收到消息)</span></span><br><span class="line">       socket.<span class="title function_">on</span>(<span class="string">&#x27;inRoom&#x27;</span>, <span class="keyword">function</span>(<span class="params">data</span>) &#123;</span><br><span class="line">           socketIo.<span class="title function_">in</span>(data.<span class="property">RoomName</span>).<span class="title function_">emit</span>(data.<span class="property">EventName</span>, data.<span class="property">Data</span>);		</span><br><span class="line">       &#125;);</span><br><span class="line"></span><br><span class="line">       socket.<span class="title function_">on</span>(<span class="string">&#x27;disconnect&#x27;</span>, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">           <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;disconnect&#x27;</span>);</span><br><span class="line">           <span class="keyword">if</span> (clientList.<span class="title function_">hasOwnProperty</span>(socket.<span class="property">id</span>)) &#123;</span><br><span class="line">               socket.<span class="title function_">disconnect</span>();</span><br><span class="line">               <span class="keyword">delete</span> clientList[socket.<span class="property">id</span>];</span><br><span class="line">           &#125;</span><br><span class="line">       &#125;);</span><br><span class="line">       <span class="comment">// 程序调用，主动断开</span></span><br><span class="line">       socket.<span class="title function_">on</span>(<span class="string">&#x27;clientDisconnect&#x27;</span>, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">           <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;clientDisconnect&#x27;</span>);</span><br><span class="line">           socket.<span class="title function_">ondisconnect</span>();</span><br><span class="line">       &#125;);</span><br><span class="line"></span><br><span class="line">       socket.<span class="title function_">on</span>(<span class="string">&#x27;error&#x27;</span>, <span class="keyword">function</span> (<span class="params">err</span>) &#123;</span><br><span class="line">           <span class="keyword">if</span> (!err) &#123; <span class="keyword">return</span> &#125;</span><br><span class="line">           <span class="keyword">try</span> &#123;</span><br><span class="line">               <span class="title class_">BaseFun</span>.<span class="title function_">errorLog</span>(<span class="string">&quot;Scoket错误&quot;</span>, <span class="string">&quot;Socket异常关闭&quot;</span>);</span><br><span class="line">           &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">               <span class="variable language_">console</span>.<span class="title function_">log</span>(err);</span><br><span class="line">           &#125;</span><br><span class="line">           <span class="keyword">if</span> (clientList.<span class="title function_">hasOwnProperty</span>(socket.<span class="property">id</span>)) &#123;</span><br><span class="line">               <span class="keyword">delete</span> clientList[socket.<span class="property">id</span>];</span><br><span class="line">           &#125;</span><br><span class="line">       &#125;);</span><br><span class="line">   &#125;);</span><br><span class="line"></span><br><span class="line">   <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;即时通信服务开启，端口号：&quot;</span> + socketPort);</span><br><span class="line"> &#125;;</span><br></pre></td></tr></table></figure>
<h2 id="补丁更新"><a href="#补丁更新" class="headerlink" title="补丁更新"></a>补丁更新</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br></pre></td><td class="code"><pre><span class="line">$scope.<span class="property">updateFile</span> = <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="title class_">BaseService</span>.<span class="title function_">filesUnzip</span>(<span class="string">&#x27;/downloads/umif-pc.zip&#x27;</span>, <span class="string">&#x27;/&#x27;</span>, <span class="keyword">function</span>(<span class="params">data</span>)&#123;</span><br><span class="line">        <span class="keyword">let</span> record = $scope.<span class="property">Module</span>.<span class="property">SystemManager</span>.<span class="property">FocusedRecord</span>;</span><br><span class="line">        <span class="keyword">if</span> (<span class="title function_">toNum</span>(record.<span class="property">NewVersion</span>) &gt; <span class="title function_">toNum</span>(record.<span class="property">Version</span> || <span class="string">&#x27;0.0.0&#x27;</span>))&#123;</span><br><span class="line">            record.<span class="property">OldVersion</span> = record.<span class="property">Version</span>;</span><br><span class="line">            record.<span class="property">OldRemark</span> = record.<span class="property">Remark</span></span><br><span class="line">            record.<span class="property">Version</span> = record.<span class="property">NewVersion</span>;</span><br><span class="line">            record.<span class="property">Remark</span> = record.<span class="property">NewRemark</span>;</span><br><span class="line">            record.<span class="property">UpdateTime</span> = <span class="keyword">new</span> <span class="title class_">Date</span>();</span><br><span class="line">            $scope.<span class="property">Module</span>.<span class="property">SystemManager</span>.<span class="title function_">save</span>();</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            record.<span class="property">OldVersion</span> = record.<span class="property">Version</span>;</span><br><span class="line">            record.<span class="property">OldRemark</span> = record.<span class="property">Remark</span></span><br><span class="line">            record.<span class="property">Version</span> = record.<span class="property">NewVersion</span>;</span><br><span class="line">            record.<span class="property">Remark</span> = record.<span class="property">NewRemark</span>;</span><br><span class="line">            record.<span class="property">UpdateTime</span> = <span class="keyword">new</span> <span class="title class_">Date</span>();</span><br><span class="line">            $scope.<span class="property">Module</span>.<span class="property">SystemManager</span>.<span class="title function_">save</span>();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="title class_">SystemManagerService</span>.<span class="title function_">updateTenantAppVersion</span>(&#123;</span><br><span class="line">            <span class="attr">tenantCode</span>: <span class="string">&#x27;tenant&#x27;</span>,</span><br><span class="line">            <span class="attr">appId</span>: <span class="string">&#x27;umif-pc&#x27;</span>,</span><br><span class="line">            <span class="attr">version</span>: record.<span class="property">NewVersion</span>,</span><br><span class="line">            <span class="attr">remark</span>: record.<span class="property">NewRemark</span></span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;, <span class="keyword">function</span>(<span class="params">error</span>) &#123;</span><br><span class="line">        <span class="title class_">BaseFunction</span>.<span class="title function_">alert</span>(error, <span class="string">&#x27;补丁更新错误&#x27;</span>);</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">exports</span>.<span class="property">filesUnzip</span> = <span class="keyword">function</span>(<span class="params">req, res</span>) &#123;</span><br><span class="line">    <span class="keyword">var</span> parameter = req.<span class="property">body</span>;</span><br><span class="line">    <span class="keyword">var</span> zipPath = process.<span class="title function_">cwd</span>() + parameter.<span class="property">zip</span>;</span><br><span class="line">    <span class="keyword">var</span> unzipPath = process.<span class="title function_">cwd</span>() + parameter.<span class="property">unzip</span>;</span><br><span class="line">    <span class="keyword">var</span> unzipExtractor = unzip.<span class="title class_">Extract</span>(&#123; <span class="attr">path</span>: unzipPath &#125;);</span><br><span class="line">    fs.<span class="title function_">exists</span>(path, <span class="keyword">function</span>(<span class="params">isExists</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (isExist) &#123;</span><br><span class="line">            fs.<span class="title function_">createReadStream</span>(zipPath).<span class="title function_">pipe</span>(unzipExtractor);</span><br><span class="line">            unzipExtractor.<span class="title function_">on</span>(<span class="string">&#x27;error&#x27;</span>, <span class="keyword">function</span>(<span class="params">err</span>) &#123;</span><br><span class="line">                res.<span class="title function_">json</span>(&#123; <span class="title class_">Error</span>: err &#125;);</span><br><span class="line">            &#125;);</span><br><span class="line">            unzipExtractor.<span class="title function_">on</span>(<span class="string">&#x27;close&#x27;</span>, <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">                res.<span class="title function_">json</span>(&#123; <span class="title class_">Data</span>: <span class="string">&#x27;close&#x27;</span> &#125;);</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            res.<span class="title function_">json</span>(&#123; <span class="title class_">Data</span>: <span class="string">&#x27;close&#x27;</span> &#125;);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 更新 AppStore 上的租户的补丁版本</span></span><br><span class="line"><span class="built_in">exports</span>.<span class="property">updateTenantAppVersion</span> = <span class="keyword">async</span> <span class="keyword">function</span>(<span class="params">req, res</span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> param = req.<span class="property">body</span>;</span><br><span class="line">    <span class="keyword">let</span> port = req.<span class="property">headers</span>.<span class="property">host</span>.<span class="title function_">split</span>(<span class="string">&#x27;:&#x27;</span>)[<span class="number">1</span>];</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">let</span> data = <span class="keyword">await</span> <span class="title function_">updateTenantAppVersion</span>(param.<span class="property">tenantCode</span>, </span><br><span class="line">        param.<span class="property">appId</span>, param.<span class="property">version</span>, param.<span class="property">remark</span>, port);</span><br><span class="line">        res.<span class="title function_">json</span>(&#123; <span class="title class_">Data</span>: data, <span class="title class_">Error</span>: <span class="literal">null</span> &#125;);</span><br><span class="line">    &#125; <span class="keyword">catch</span> (error) &#123;</span><br><span class="line">        res.<span class="title function_">json</span>(&#123; <span class="title class_">Data</span>: <span class="literal">null</span>, <span class="title class_">Error</span>: error &#125;);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 远程调用更新 TenantAppVersion</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">updateTenantAppVersion</span>(<span class="params">tenantCode, appId, version, </span></span><br><span class="line"><span class="params">    remark, port1</span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> param = <span class="keyword">await</span> entityFun.<span class="title function_">findOne</span>(<span class="string">&#x27;Parameter&#x27;</span>, &#123;<span class="title class_">Code</span>: <span class="string">&#x27;AppStore&#x27;</span>&#125;);</span><br><span class="line">    <span class="keyword">if</span> (!param) &#123; <span class="keyword">return</span> &#125;</span><br><span class="line">    <span class="keyword">let</span> url = param.<span class="property">Value</span>;</span><br><span class="line">    <span class="keyword">let</span> ip = <span class="string">&quot;127.0.0.1&quot;</span>;</span><br><span class="line">    <span class="keyword">let</span> port = <span class="number">80</span>;</span><br><span class="line">    <span class="keyword">if</span> (url.<span class="title function_">indexOf</span>(<span class="string">&#x27;:&#x27;</span>) &gt; -<span class="number">1</span>) &#123;</span><br><span class="line">        ip = url.<span class="title function_">split</span>(<span class="string">&#x27;:&#x27;</span>)[<span class="number">0</span>];</span><br><span class="line">        port = url.<span class="title function_">split</span>(<span class="string">&#x27;:&#x27;</span>)[<span class="number">1</span>];</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        ip = url;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">let</span> options = &#123;</span><br><span class="line">        <span class="attr">hostname</span>: ip,</span><br><span class="line">        <span class="attr">port</span>: port,</span><br><span class="line">        <span class="attr">method</span>: <span class="string">&#x27;Post&#x27;</span>,</span><br><span class="line">        <span class="attr">path</span>: <span class="string">&#x27;/api/tenant/httpUpdateTenantAppVersion&#x27;</span></span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">let</span> data = &#123;</span><br><span class="line">        <span class="attr">tenantCode</span>: tenantCode,</span><br><span class="line">        <span class="attr">appId</span>: appId,</span><br><span class="line">        <span class="attr">version</span>: version,</span><br><span class="line">        <span class="attr">remark</span>: remark,</span><br><span class="line">        <span class="attr">envType</span>: <span class="literal">null</span>,</span><br><span class="line">        <span class="attr">port</span>: port1</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (<span class="title class_">BaseFun</span>.<span class="title function_">verifyIp</span>(ip)) &#123;</span><br><span class="line">        <span class="keyword">await</span> <span class="title class_">BaseFun</span>.<span class="title function_">requestHttp</span>(options, data);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">let</span> url = <span class="string">&#x27;https://&#x27;</span> + options.<span class="property">hostname</span> + options.<span class="property">path</span>;</span><br><span class="line">        <span class="keyword">await</span> <span class="title class_">BaseFun</span>.<span class="title function_">axios</span>(options.<span class="property">method</span>, url, data);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">exports</span>.<span class="property">requestHttp</span> = <span class="keyword">function</span>(<span class="params">options, parameter, isParse</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="keyword">function</span>(<span class="params">resolve, reject</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (!options.<span class="property">path</span>) &#123;</span><br><span class="line">            <span class="keyword">var</span> newErr = <span class="keyword">new</span> <span class="title class_">Error</span>();</span><br><span class="line">            newErr.<span class="property">leval</span> = <span class="number">9</span>;</span><br><span class="line">            newErr.<span class="property">title</span> = <span class="string">&#x27;请求服务器错误&#x27;</span>;</span><br><span class="line">            newErr.<span class="property">message</span> = <span class="string">&#x27;没有传入路径参数&#x27;</span>;</span><br><span class="line">            <span class="title function_">reject</span>(newErr);</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (parameter) &#123;</span><br><span class="line">            parameter = <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(parameter);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (!options.<span class="property">hostname</span>) &#123;</span><br><span class="line">            options.<span class="property">hostname</span> = <span class="string">&#x27;127.0.0.1&#x27;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (!options.<span class="property">port</span>) &#123;</span><br><span class="line">            options.<span class="property">port</span> = <span class="number">3000</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (!options.<span class="property">method</span>) &#123;</span><br><span class="line">            options.<span class="property">method</span> = <span class="string">&#x27;POST&#x27;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (!options.<span class="property">headers</span>) &#123;</span><br><span class="line">            options.<span class="property">headers</span> = &#123; <span class="string">&quot;Content-Type&quot;</span>: <span class="string">&#x27;application/json&#x27;</span> &#125;;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">var</span> req = http.<span class="title function_">request</span>(options, <span class="keyword">function</span>(<span class="params">res</span>) &#123;</span><br><span class="line">            <span class="keyword">var</span> result = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">            res.<span class="title function_">on</span>(<span class="string">&#x27;data&#x27;</span>, <span class="keyword">function</span>(<span class="params">data</span>) &#123;</span><br><span class="line">                result += data;</span><br><span class="line">            &#125;).<span class="title function_">on</span>(<span class="string">&#x27;end&#x27;</span>, <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    result = isParse ? result : <span class="title class_">JSON</span>.<span class="title function_">parse</span>(result);</span><br><span class="line">                &#125; <span class="keyword">catch</span> (ex) &#123;</span><br><span class="line">                    result = &#123; <span class="title class_">Error</span>: result &#125;;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">if</span> (result.<span class="property">Error</span>) &#123;</span><br><span class="line">                    <span class="title function_">reject</span>(result.<span class="property">Error</span>);</span><br><span class="line">                &#125; <span class="keyword">else</span> <span class="keyword">if</span> (result.<span class="property">Data</span>) &#123;</span><br><span class="line">                    <span class="title function_">resolve</span>(result.<span class="property">Data</span>);</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="title function_">resolve</span>(result);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (parameter) &#123;</span><br><span class="line">            req.<span class="title function_">write</span>(parameter);</span><br><span class="line">        &#125;</span><br><span class="line">        req.<span class="title function_">on</span>(<span class="string">&#x27;error&#x27;</span>, <span class="function">(<span class="params">err</span>) =&gt;</span> &#123;</span><br><span class="line">            <span class="title function_">reject</span>(err);</span><br><span class="line">        &#125;);</span><br><span class="line">        req.<span class="title function_">end</span>();</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>


<h2 id="补丁还原"><a href="#补丁还原" class="headerlink" title="补丁还原"></a>补丁还原</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">$scope.<span class="property">reductionFile</span> = <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="title class_">BaseService</span>.<span class="title function_">filesUnzip</span>(<span class="string">&#x27;/downloads/umif-pc-back.zip&#x27;</span>, <span class="string">&#x27;/&#x27;</span>, </span><br><span class="line">    <span class="keyword">function</span>(<span class="params">data</span>) &#123;</span><br><span class="line">        <span class="keyword">let</span> record = $scope.<span class="property">Module</span>.<span class="property">SystemManager</span>.<span class="property">FocusedRecord</span>;</span><br><span class="line">        record.<span class="property">Version</span> = record.<span class="property">OldVersion</span>;</span><br><span class="line">        record.<span class="property">Remark</span> = record.<span class="property">OldRemark</span>;</span><br><span class="line">        record.<span class="property">UpdateTime</span> = <span class="keyword">new</span> <span class="title class_">Date</span>();</span><br><span class="line">        $scope.<span class="property">Module</span>.<span class="property">SystemManager</span>.<span class="title function_">save</span>();</span><br><span class="line">        <span class="keyword">let</span> param = &#123;</span><br><span class="line">            <span class="attr">tenantCode</span>: <span class="string">&#x27;tenant&#x27;</span>,</span><br><span class="line">            <span class="attr">appId</span>: <span class="string">&#x27;umif-pc&#x27;</span>,</span><br><span class="line">            <span class="attr">version</span>: record.<span class="property">OldVersion</span>,</span><br><span class="line">            <span class="attr">remark</span>: record.<span class="property">NewRemark</span>,</span><br><span class="line">        &#125;;</span><br><span class="line">        <span class="title class_">SystemManagerService</span>.<span class="title function_">updateTenantAppVersion</span>(param);</span><br><span class="line">    &#125;, <span class="keyword">function</span>(<span class="params">error</span>) &#123;</span><br><span class="line">        <span class="title class_">BaseFunction</span>.<span class="title function_">alert</span>(error, <span class="string">&#x27;补丁更新错误&#x27;</span>);</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>










    </div>

    
    
    <div>
      
        <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;margin-top:20px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>

      
    </div>
    
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>chuangges
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://chuangges.gitee.io/2023/01/17/20-%E8%B7%A8%E5%B9%B3%E5%8F%B0%E6%96%87%E6%A1%A3/" title="文档的在线预览和上传下载">https://chuangges.gitee.io/2023/01/17/20-跨平台文档/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/zh_CN" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2023/01/10/19-%E7%99%BE%E5%BA%A6%E8%AF%86%E5%88%AB/" rel="prev" title="百度智能云之在线识别">
      <i class="fa fa-chevron-left"></i> 百度智能云之在线识别
    </a></div>
      <div class="post-nav-item">
    <a href="/2023/03/02/21-vue3%E9%A1%B9%E7%9B%AE%E5%BC%80%E5%8F%91/" rel="next" title="Vue3 项目开发">
      Vue3 项目开发 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%80%E3%80%81vue-%E5%9C%A8%E7%BA%BF%E9%A2%84%E8%A7%88"><span class="nav-number">1.</span> <span class="nav-text">一、vue 在线预览</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Docx"><span class="nav-number">1.1.</span> <span class="nav-text">Docx</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Pdf"><span class="nav-number">1.2.</span> <span class="nav-text">Pdf</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Excel"><span class="nav-number">1.3.</span> <span class="nav-text">Excel</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#pptx"><span class="nav-number">1.4.</span> <span class="nav-text">pptx</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%8C%E3%80%81vue-%E6%96%87%E4%BB%B6%E5%88%86%E5%9D%97%E4%B8%8A%E4%BC%A0"><span class="nav-number">2.</span> <span class="nav-text">二、vue 文件分块上传</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%96%87%E4%BB%B6%E6%B5%81%E6%93%8D%E4%BD%9C"><span class="nav-number">2.1.</span> <span class="nav-text">文件流操作</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%88%87%E7%89%87%E4%B8%8A%E4%BC%A0"><span class="nav-number">2.2.</span> <span class="nav-text">切片上传</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%88%87%E7%89%87%E4%B8%8B%E8%BD%BD"><span class="nav-number">2.3.</span> <span class="nav-text">切片下载</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%A4%84%E7%90%86"><span class="nav-number">2.4.</span> <span class="nav-text">服务端处理</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%89%E3%80%81uniapp-%E5%9C%A8%E7%BA%BF%E9%A2%84%E8%A7%88"><span class="nav-number">3.</span> <span class="nav-text">三、uniapp 在线预览</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#PDF"><span class="nav-number">3.1.</span> <span class="nav-text">PDF</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Office"><span class="nav-number">3.2.</span> <span class="nav-text">Office</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Image"><span class="nav-number">3.3.</span> <span class="nav-text">Image</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Docx-1"><span class="nav-number">3.4.</span> <span class="nav-text">Docx</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%9B%9B%E3%80%81uniapp-%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0"><span class="nav-number">4.</span> <span class="nav-text">四、uniapp 文件上传</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9B%BE%E7%89%87%E4%B8%8A%E4%BC%A0"><span class="nav-number">4.1.</span> <span class="nav-text">图片上传</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%A7%86%E9%A2%91%E4%B8%8A%E4%BC%A0"><span class="nav-number">4.2.</span> <span class="nav-text">视频上传</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%96%87%E6%A1%A3%E4%B8%8A%E4%BC%A0"><span class="nav-number">4.3.</span> <span class="nav-text">文档上传</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%9B%AE%E5%BD%95%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0"><span class="nav-number">4.4.</span> <span class="nav-text">目录文件上传</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%94%E3%80%81minio-%E6%96%87%E4%BB%B6%E7%AE%A1%E7%90%86"><span class="nav-number">5.</span> <span class="nav-text">五、minio 文件管理</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Node-%E9%A1%B9%E7%9B%AE%E9%9B%86%E6%88%90"><span class="nav-number">5.1.</span> <span class="nav-text">Node 项目集成</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#JS-%E5%90%8E%E5%8F%B0%E5%B0%81%E8%A3%85"><span class="nav-number">5.2.</span> <span class="nav-text">JS 后台封装</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#JS-%E5%89%8D%E5%8F%B0%E8%B0%83%E7%94%A8"><span class="nav-number">5.3.</span> <span class="nav-text">JS 前台调用</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%85%AD%E3%80%81%E8%A1%A5%E4%B8%81%E7%89%88%E6%9C%AC%E7%AE%A1%E7%90%86"><span class="nav-number">6.</span> <span class="nav-text">六、补丁版本管理</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%A1%A5%E4%B8%81%E4%B8%8B%E8%BD%BD"><span class="nav-number">6.1.</span> <span class="nav-text">补丁下载</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%A1%A5%E4%B8%81%E6%9B%B4%E6%96%B0"><span class="nav-number">6.2.</span> <span class="nav-text">补丁更新</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%A1%A5%E4%B8%81%E8%BF%98%E5%8E%9F"><span class="nav-number">6.3.</span> <span class="nav-text">补丁还原</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="chuangges" src="" data-original="/images/chuang.png">
  <p class="site-author-name" itemprop="name">chuangges</p>
  <div class="site-description" itemprop="description">chuangge's blog.</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">39</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/chuangges" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;chuangges" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://stackoverflow.com/yourname" title="StackOverflow → https:&#x2F;&#x2F;stackoverflow.com&#x2F;yourname" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-stack-overflow fa-fw"></i>StackOverflow</a>
      </span>
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title"><i class="fa fa-link fa-fw"></i>
      友情链接
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="https://juejin.im/" title="https:&#x2F;&#x2F;juejin.im&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">掘金</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://www.nowcoder.com/" title="https:&#x2F;&#x2F;www.nowcoder.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">牛客网</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://www.docschina.org/" title="https:&#x2F;&#x2F;www.docschina.org&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">印记中文</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="http://tool.lu/" title="http:&#x2F;&#x2F;tool.lu&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">在线工具</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://tinypng.com/" title="https:&#x2F;&#x2F;tinypng.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">图片压缩</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://bigjpg.com/" title="https:&#x2F;&#x2F;bigjpg.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">图片放大</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://tool.chinaz.com/" title="https:&#x2F;&#x2F;tool.chinaz.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">站长工具</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://learn-anything.xyz/" title="https:&#x2F;&#x2F;learn-anything.xyz&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">Learn-Anything</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://stackoverflow.com/" title="https:&#x2F;&#x2F;stackoverflow.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">Stack-Overflow</a>
        </li>
    </ul>
  </div>

      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2024</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">chuangge</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-area"></i>
    </span>
    <span title="站点总字数">1m</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
    <span title="站点阅读时长">15:14</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="external nofollow noopener noreferrer" target="_blank">Hexo</a> & <a href="https://pisces.theme-next.org/" class="theme-link" rel="external nofollow noopener noreferrer" target="_blank">NexT.Pisces</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","model":{"jsonPath":"/live2dw/assets/tororo.model.json"},"display":{"position":"left","width":180,"height":360},"mobile":{"show":false},"react":{"opacityDefault":1,"opacityOnHover":1},"log":false,"tagMode":false});</script>
        <style>
            [bg-lazy] {
                background-image: none !important;
                background-color: #eee !important;
            }
        </style>
        <script>
            window.imageLazyLoadSetting = {
                isSPA: false,
                preloadRatio: 1,
                processImages: null,
            };
        </script><script>window.addEventListener("load",function(){var t=/\.(gif|jpg|jpeg|tiff|png)$/i,r=/^data:image\/[a-z]+;base64,/;Array.prototype.slice.call(document.querySelectorAll("img[data-original]")).forEach(function(a){var e=a.parentNode;"A"===e.tagName&&(e.href.match(t)||e.href.match(r))&&(e.href=a.dataset.original)})});</script><script>!function(e){e.imageLazyLoadSetting.processImages=t;var n=e.imageLazyLoadSetting.isSPA,i=e.imageLazyLoadSetting.preloadRatio||1,r=o();function o(){var t=Array.prototype.slice.call(document.querySelectorAll("img[data-original]")),e=Array.prototype.slice.call(document.querySelectorAll("[bg-lazy]"));return t.concat(e)}function t(){n&&(r=o());for(var t,a=0;a<r.length;a++)0<=(t=(t=r[a]).getBoundingClientRect()).bottom&&0<=t.left&&t.top<=(e.innerHeight*i||document.documentElement.clientHeight*i)&&function(){var t,e,n,i,o=r[a];e=function(){r=r.filter(function(t){return o!==t})},(t=o).hasAttribute("bg-lazy")?(t.removeAttribute("bg-lazy"),e&&e()):(n=new Image,i=t.getAttribute("data-original"),n.onload=function(){t.src=i,t.removeAttribute("data-original"),e&&e()},t.src!==i&&(n.src=i))}()}function a(){clearTimeout(t.tId),t.tId=setTimeout(t,500)}t(),document.addEventListener("scroll",a),e.addEventListener("resize",a),e.addEventListener("orientationchange",a)}(this);</script></body>
</html>
